1:
67:
68: package ;
69:
70: import ;
71: import ;
72: import ;
73: import ;
74: import ;
75: import ;
76: import ;
77: import ;
78: import ;
79: import ;
80: import ;
81: import ;
82: import ;
83: import ;
84: import ;
85: import ;
86: import ;
87: import ;
88: import ;
89:
90: import ;
91: import ;
92: import ;
93: import ;
94: import ;
95: import ;
96: import ;
97: import ;
98: import ;
99: import ;
100: import ;
101: import ;
102: import ;
103: import ;
104: import ;
105: import ;
106: import ;
107: import ;
108: import ;
109: import ;
110: import ;
111:
112:
118: public class ContourPlot extends Plot implements ContourValuePlot,
119: ValueAxisPlot,
120: PropertyChangeListener,
121: Serializable,
122: Cloneable {
123:
124:
125: private static final long serialVersionUID = 7861072556590502247L;
126:
127:
128: protected static final RectangleInsets DEFAULT_INSETS
129: = new RectangleInsets(2.0, 2.0, 100.0, 10.0);
130:
131:
132: private ValueAxis domainAxis;
133:
134:
135: private ValueAxis rangeAxis;
136:
137:
138: private ContourDataset dataset;
139:
140:
141: private ColorBar colorBar = null;
142:
143:
144: private RectangleEdge colorBarLocation;
145:
146:
147: private boolean domainCrosshairVisible;
148:
149:
150: private double domainCrosshairValue;
151:
152:
153: private transient Stroke domainCrosshairStroke;
154:
155:
156: private transient Paint domainCrosshairPaint;
157:
158:
162: private boolean domainCrosshairLockedOnData = true;
163:
164:
165: private boolean rangeCrosshairVisible;
166:
167:
168: private double rangeCrosshairValue;
169:
170:
171: private transient Stroke rangeCrosshairStroke;
172:
173:
174: private transient Paint rangeCrosshairPaint;
175:
176:
180: private boolean rangeCrosshairLockedOnData = true;
181:
182:
191: private double dataAreaRatio = 0.0;
192:
193:
194: private List domainMarkers;
195:
196:
197: private List rangeMarkers;
198:
199:
200: private List annotations;
201:
202:
203: private ContourToolTipGenerator toolTipGenerator;
204:
205:
206: private XYURLGenerator urlGenerator;
207:
208:
212: private boolean renderAsPoints = false;
213:
214:
218: private double ptSizePct = 0.05;
219:
220:
221: private transient ClipPath clipPath = null;
222:
223:
224: private transient Paint missingPaint = null;
225:
226:
227: protected static ResourceBundle localizationResources =
228: ResourceBundle.getBundle("org.jfree.chart.plot.LocalizationBundle");
229:
230:
233: public ContourPlot() {
234: this(null, null, null, null);
235: }
236:
237:
246: public ContourPlot(ContourDataset dataset,
247: ValueAxis domainAxis, ValueAxis rangeAxis,
248: ColorBar colorBar) {
249:
250: super();
251:
252: this.dataset = dataset;
253: if (dataset != null) {
254: dataset.addChangeListener(this);
255: }
256:
257: this.domainAxis = domainAxis;
258: if (domainAxis != null) {
259: domainAxis.setPlot(this);
260: domainAxis.addChangeListener(this);
261: }
262:
263: this.rangeAxis = rangeAxis;
264: if (rangeAxis != null) {
265: rangeAxis.setPlot(this);
266: rangeAxis.addChangeListener(this);
267: }
268:
269: this.colorBar = colorBar;
270: if (colorBar != null) {
271: colorBar.getAxis().setPlot(this);
272: colorBar.getAxis().addChangeListener(this);
273: colorBar.configure(this);
274: }
275: this.colorBarLocation = RectangleEdge.LEFT;
276:
277: this.toolTipGenerator = new StandardContourToolTipGenerator();
278:
279: }
280:
281:
286: public RectangleEdge getColorBarLocation() {
287: return this.colorBarLocation;
288: }
289:
290:
296: public void setColorBarLocation(RectangleEdge edge) {
297: this.colorBarLocation = edge;
298: notifyListeners(new PlotChangeEvent(this));
299: }
300:
301:
306: public ContourDataset getDataset() {
307: return this.dataset;
308: }
309:
310:
316: public void setDataset(ContourDataset dataset) {
317:
318:
319:
320: ContourDataset existing = this.dataset;
321: if (existing != null) {
322: existing.removeChangeListener(this);
323: }
324:
325:
326: this.dataset = dataset;
327: if (dataset != null) {
328: setDatasetGroup(dataset.getGroup());
329: dataset.addChangeListener(this);
330: }
331:
332:
333: DatasetChangeEvent event = new DatasetChangeEvent(this, dataset);
334: datasetChanged(event);
335:
336: }
337:
338:
343: public ValueAxis getDomainAxis() {
344:
345: ValueAxis result = this.domainAxis;
346:
347: return result;
348:
349: }
350:
351:
357: public void setDomainAxis(ValueAxis axis) {
358:
359: if (isCompatibleDomainAxis(axis)) {
360:
361: if (axis != null) {
362: axis.setPlot(this);
363: axis.addChangeListener(this);
364: }
365:
366:
367: if (this.domainAxis != null) {
368: this.domainAxis.removeChangeListener(this);
369: }
370:
371: this.domainAxis = axis;
372: notifyListeners(new PlotChangeEvent(this));
373:
374: }
375:
376: }
377:
378:
383: public ValueAxis getRangeAxis() {
384:
385: ValueAxis result = this.rangeAxis;
386:
387: return result;
388:
389: }
390:
391:
399: public void setRangeAxis(ValueAxis axis) {
400:
401: if (axis != null) {
402: axis.setPlot(this);
403: axis.addChangeListener(this);
404: }
405:
406:
407: if (this.rangeAxis != null) {
408: this.rangeAxis.removeChangeListener(this);
409: }
410:
411: this.rangeAxis = axis;
412: notifyListeners(new PlotChangeEvent(this));
413:
414: }
415:
416:
421: public void setColorBarAxis(ColorBar axis) {
422:
423: this.colorBar = axis;
424: notifyListeners(new PlotChangeEvent(this));
425:
426: }
427:
428:
433: public double getDataAreaRatio() {
434: return this.dataAreaRatio;
435: }
436:
437:
442: public void setDataAreaRatio(double ratio) {
443: this.dataAreaRatio = ratio;
444: }
445:
446:
454: public void addDomainMarker(Marker marker) {
455:
456: if (this.domainMarkers == null) {
457: this.domainMarkers = new java.util.ArrayList();
458: }
459: this.domainMarkers.add(marker);
460: notifyListeners(new PlotChangeEvent(this));
461:
462: }
463:
464:
467: public void clearDomainMarkers() {
468: if (this.domainMarkers != null) {
469: this.domainMarkers.clear();
470: notifyListeners(new PlotChangeEvent(this));
471: }
472: }
473:
474:
482: public void addRangeMarker(Marker marker) {
483:
484: if (this.rangeMarkers == null) {
485: this.rangeMarkers = new java.util.ArrayList();
486: }
487: this.rangeMarkers.add(marker);
488: notifyListeners(new PlotChangeEvent(this));
489:
490: }
491:
492:
495: public void clearRangeMarkers() {
496: if (this.rangeMarkers != null) {
497: this.rangeMarkers.clear();
498: notifyListeners(new PlotChangeEvent(this));
499: }
500: }
501:
502:
507: public void addAnnotation(XYAnnotation annotation) {
508:
509: if (this.annotations == null) {
510: this.annotations = new java.util.ArrayList();
511: }
512: this.annotations.add(annotation);
513: notifyListeners(new PlotChangeEvent(this));
514:
515: }
516:
517:
520: public void clearAnnotations() {
521: if (this.annotations != null) {
522: this.annotations.clear();
523: notifyListeners(new PlotChangeEvent(this));
524: }
525: }
526:
527:
535: public boolean isCompatibleDomainAxis(ValueAxis axis) {
536:
537: return true;
538:
539: }
540:
541:
557: public void draw(Graphics2D g2, Rectangle2D area, Point2D anchor,
558: PlotState parentState,
559: PlotRenderingInfo info) {
560:
561:
562: boolean b1 = (area.getWidth() <= MINIMUM_WIDTH_TO_DRAW);
563: boolean b2 = (area.getHeight() <= MINIMUM_HEIGHT_TO_DRAW);
564: if (b1 || b2) {
565: return;
566: }
567:
568:
569: if (info != null) {
570: info.setPlotArea(area);
571: }
572:
573:
574: RectangleInsets insets = getInsets();
575: insets.trim(area);
576:
577: AxisSpace space = new AxisSpace();
578:
579: space = this.domainAxis.reserveSpace(g2, this, area,
580: RectangleEdge.BOTTOM, space);
581: space = this.rangeAxis.reserveSpace(g2, this, area,
582: RectangleEdge.LEFT, space);
583:
584: Rectangle2D estimatedDataArea = space.shrink(area, null);
585:
586: AxisSpace space2 = new AxisSpace();
587: space2 = this.colorBar.reserveSpace(g2, this, area, estimatedDataArea,
588: this.colorBarLocation, space2);
589: Rectangle2D adjustedPlotArea = space2.shrink(area, null);
590:
591: Rectangle2D dataArea = space.shrink(adjustedPlotArea, null);
592:
593: Rectangle2D colorBarArea = space2.reserved(area, this.colorBarLocation);
594:
595:
596: if (getDataAreaRatio() != 0.0) {
597: double ratio = getDataAreaRatio();
598: Rectangle2D tmpDataArea = (Rectangle2D) dataArea.clone();
599: double h = tmpDataArea.getHeight();
600: double w = tmpDataArea.getWidth();
601:
602: if (ratio > 0) {
603: if (w * ratio <= h) {
604: h = ratio * w;
605: }
606: else {
607: w = h / ratio;
608: }
609: }
610: else {
611: ratio *= -1.0;
612: double xLength = getDomainAxis().getRange().getLength();
613: double yLength = getRangeAxis().getRange().getLength();
614: double unitRatio = yLength / xLength;
615:
616: ratio = unitRatio * ratio;
617:
618: if (w * ratio <= h) {
619: h = ratio * w;
620: }
621: else {
622: w = h / ratio;
623: }
624: }
625:
626: dataArea.setRect(tmpDataArea.getX() + tmpDataArea.getWidth() / 2
627: - w / 2, tmpDataArea.getY(), w, h);
628: }
629:
630: if (info != null) {
631: info.setDataArea(dataArea);
632: }
633:
634: CrosshairState crosshairState = new CrosshairState();
635: crosshairState.setCrosshairDistance(Double.POSITIVE_INFINITY);
636:
637:
638: drawBackground(g2, dataArea);
639:
640: double cursor = dataArea.getMaxY();
641: if (this.domainAxis != null) {
642: this.domainAxis.draw(g2, cursor, adjustedPlotArea, dataArea,
643: RectangleEdge.BOTTOM, info);
644: }
645:
646: if (this.rangeAxis != null) {
647: cursor = dataArea.getMinX();
648: this.rangeAxis.draw(g2, cursor, adjustedPlotArea, dataArea,
649: RectangleEdge.LEFT, info);
650: }
651:
652: if (this.colorBar != null) {
653: cursor = 0.0;
654: cursor = this.colorBar.draw(g2, cursor, adjustedPlotArea, dataArea,
655: colorBarArea, this.colorBarLocation);
656: }
657: Shape originalClip = g2.getClip();
658: Composite originalComposite = g2.getComposite();
659:
660: g2.clip(dataArea);
661: g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
662: getForegroundAlpha()));
663: render(g2, dataArea, info, crosshairState);
664:
665: if (this.domainMarkers != null) {
666: Iterator iterator = this.domainMarkers.iterator();
667: while (iterator.hasNext()) {
668: Marker marker = (Marker) iterator.next();
669: drawDomainMarker(g2, this, getDomainAxis(), marker, dataArea);
670: }
671: }
672:
673: if (this.rangeMarkers != null) {
674: Iterator iterator = this.rangeMarkers.iterator();
675: while (iterator.hasNext()) {
676: Marker marker = (Marker) iterator.next();
677: drawRangeMarker(g2, this, getRangeAxis(), marker, dataArea);
678: }
679: }
680:
681:
682:
683:
684:
685:
686:
687:
688:
689:
690:
691:
692:
693:
694:
695:
696:
697:
698: g2.setClip(originalClip);
699: g2.setComposite(originalComposite);
700: drawOutline(g2, dataArea);
701:
702: }
703:
704:
716: public void render(Graphics2D g2, Rectangle2D dataArea,
717: PlotRenderingInfo info, CrosshairState crosshairState) {
718:
719:
720:
721: ContourDataset data = getDataset();
722: if (data != null) {
723:
724: ColorBar zAxis = getColorBar();
725:
726: if (this.clipPath != null) {
727: GeneralPath clipper = getClipPath().draw(g2, dataArea,
728: this.domainAxis, this.rangeAxis);
729: if (this.clipPath.isClip()) {
730: g2.clip(clipper);
731: }
732: }
733:
734: if (this.renderAsPoints) {
735: pointRenderer(g2, dataArea, info, this, this.domainAxis,
736: this.rangeAxis, zAxis, data, crosshairState);
737: }
738: else {
739: contourRenderer(g2, dataArea, info, this, this.domainAxis,
740: this.rangeAxis, zAxis, data, crosshairState);
741: }
742:
743:
744: setDomainCrosshairValue(crosshairState.getCrosshairX(), false);
745: if (isDomainCrosshairVisible()) {
746: drawVerticalLine(g2, dataArea,
747: getDomainCrosshairValue(),
748: getDomainCrosshairStroke(),
749: getDomainCrosshairPaint());
750: }
751:
752:
753: setRangeCrosshairValue(crosshairState.getCrosshairY(), false);
754: if (isRangeCrosshairVisible()) {
755: drawHorizontalLine(g2, dataArea,
756: getRangeCrosshairValue(),
757: getRangeCrosshairStroke(),
758: getRangeCrosshairPaint());
759: }
760:
761: }
762: else if (this.clipPath != null) {
763: getClipPath().draw(g2, dataArea, this.domainAxis, this.rangeAxis);
764: }
765:
766: }
767:
768:
782: public void contourRenderer(Graphics2D g2,
783: Rectangle2D dataArea,
784: PlotRenderingInfo info,
785: ContourPlot plot,
786: ValueAxis horizontalAxis,
787: ValueAxis verticalAxis,
788: ColorBar colorBar,
789: ContourDataset data,
790: CrosshairState crosshairState) {
791:
792:
793: Rectangle2D.Double entityArea = null;
794: EntityCollection entities = null;
795: if (info != null) {
796: entities = info.getOwner().getEntityCollection();
797: }
798:
799: Rectangle2D.Double rect = null;
800: rect = new Rectangle2D.Double();
801:
802:
803: Object antiAlias = g2.getRenderingHint(RenderingHints.KEY_ANTIALIASING);
804: g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
805: RenderingHints.VALUE_ANTIALIAS_OFF);
806:
807:
808: Number[] xNumber = data.getXValues();
809: Number[] yNumber = data.getYValues();
810: Number[] zNumber = data.getZValues();
811:
812: double[] x = new double[xNumber.length];
813: double[] y = new double[yNumber.length];
814:
815: for (int i = 0; i < x.length; i++) {
816: x[i] = xNumber[i].doubleValue();
817: y[i] = yNumber[i].doubleValue();
818: }
819:
820: int[] xIndex = data.indexX();
821: int[] indexX = data.getXIndices();
822: boolean vertInverted = ((NumberAxis) verticalAxis).isInverted();
823: boolean horizInverted = false;
824: if (horizontalAxis instanceof NumberAxis) {
825: horizInverted = ((NumberAxis) horizontalAxis).isInverted();
826: }
827: double transX = 0.0;
828: double transXm1 = 0.0;
829: double transXp1 = 0.0;
830: double transDXm1 = 0.0;
831: double transDXp1 = 0.0;
832: double transDX = 0.0;
833: double transY = 0.0;
834: double transYm1 = 0.0;
835: double transYp1 = 0.0;
836: double transDYm1 = 0.0;
837: double transDYp1 = 0.0;
838: double transDY = 0.0;
839: int iMax = xIndex[xIndex.length - 1];
840: for (int k = 0; k < x.length; k++) {
841: int i = xIndex[k];
842: if (indexX[i] == k) {
843: if (i == 0) {
844: transX = horizontalAxis.valueToJava2D(x[k], dataArea,
845: RectangleEdge.BOTTOM);
846: transXm1 = transX;
847: transXp1 = horizontalAxis.valueToJava2D(
848: x[indexX[i + 1]], dataArea, RectangleEdge.BOTTOM);
849: transDXm1 = Math.abs(0.5 * (transX - transXm1));
850: transDXp1 = Math.abs(0.5 * (transX - transXp1));
851: }
852: else if (i == iMax) {
853: transX = horizontalAxis.valueToJava2D(x[k], dataArea,
854: RectangleEdge.BOTTOM);
855: transXm1 = horizontalAxis.valueToJava2D(x[indexX[i - 1]],
856: dataArea, RectangleEdge.BOTTOM);
857: transXp1 = transX;
858: transDXm1 = Math.abs(0.5 * (transX - transXm1));
859: transDXp1 = Math.abs(0.5 * (transX - transXp1));
860: }
861: else {
862: transX = horizontalAxis.valueToJava2D(x[k], dataArea,
863: RectangleEdge.BOTTOM);
864: transXp1 = horizontalAxis.valueToJava2D(x[indexX[i + 1]],
865: dataArea, RectangleEdge.BOTTOM);
866: transDXm1 = transDXp1;
867: transDXp1 = Math.abs(0.5 * (transX - transXp1));
868: }
869:
870: if (horizInverted) {
871: transX -= transDXp1;
872: }
873: else {
874: transX -= transDXm1;
875: }
876:
877: transDX = transDXm1 + transDXp1;
878:
879: transY = verticalAxis.valueToJava2D(y[k], dataArea,
880: RectangleEdge.LEFT);
881: transYm1 = transY;
882: if (k + 1 == y.length) {
883: continue;
884: }
885: transYp1 = verticalAxis.valueToJava2D(y[k + 1], dataArea,
886: RectangleEdge.LEFT);
887: transDYm1 = Math.abs(0.5 * (transY - transYm1));
888: transDYp1 = Math.abs(0.5 * (transY - transYp1));
889: }
890: else if ((i < indexX.length - 1
891: && indexX[i + 1] - 1 == k) || k == x.length - 1) {
892:
893: transY = verticalAxis.valueToJava2D(y[k], dataArea,
894: RectangleEdge.LEFT);
895: transYm1 = verticalAxis.valueToJava2D(y[k - 1], dataArea,
896: RectangleEdge.LEFT);
897: transYp1 = transY;
898: transDYm1 = Math.abs(0.5 * (transY - transYm1));
899: transDYp1 = Math.abs(0.5 * (transY - transYp1));
900: }
901: else {
902: transY = verticalAxis.valueToJava2D(y[k], dataArea,
903: RectangleEdge.LEFT);
904: transYp1 = verticalAxis.valueToJava2D(y[k + 1], dataArea,
905: RectangleEdge.LEFT);
906: transDYm1 = transDYp1;
907: transDYp1 = Math.abs(0.5 * (transY - transYp1));
908: }
909: if (vertInverted) {
910: transY -= transDYm1;
911: }
912: else {
913: transY -= transDYp1;
914: }
915:
916: transDY = transDYm1 + transDYp1;
917:
918: rect.setRect(transX, transY, transDX, transDY);
919: if (zNumber[k] != null) {
920: g2.setPaint(colorBar.getPaint(zNumber[k].doubleValue()));
921: g2.fill(rect);
922: }
923: else if (this.missingPaint != null) {
924: g2.setPaint(this.missingPaint);
925: g2.fill(rect);
926: }
927:
928: entityArea = rect;
929:
930:
931: if (entities != null) {
932: String tip = "";
933: if (getToolTipGenerator() != null) {
934: tip = this.toolTipGenerator.generateToolTip(data, k);
935: }
936:
937:
938: String url = null;
939:
940:
941:
942:
943:
944: ContourEntity entity = new ContourEntity(
945: (Rectangle2D.Double) entityArea.clone(), tip, url);
946: entity.setIndex(k);
947: entities.add(entity);
948:
949: }
950:
951:
952: if (plot.isDomainCrosshairLockedOnData()) {
953: if (plot.isRangeCrosshairLockedOnData()) {
954:
955: crosshairState.updateCrosshairPoint(x[k], y[k], transX,
956: transY, PlotOrientation.VERTICAL);
957: }
958: else {
959:
960: crosshairState.updateCrosshairX(transX);
961: }
962: }
963: else {
964: if (plot.isRangeCrosshairLockedOnData()) {
965:
966: crosshairState.updateCrosshairY(transY);
967: }
968: }
969: }
970:
971: g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, antiAlias);
972:
973: return;
974:
975: }
976:
977:
991: public void pointRenderer(Graphics2D g2,
992: Rectangle2D dataArea,
993: PlotRenderingInfo info,
994: ContourPlot plot,
995: ValueAxis domainAxis,
996: ValueAxis rangeAxis,
997: ColorBar colorBar,
998: ContourDataset data,
999: CrosshairState crosshairState) {
1000:
1001:
1002: RectangularShape entityArea = null;
1003: EntityCollection entities = null;
1004: if (info != null) {
1005: entities = info.getOwner().getEntityCollection();
1006: }
1007:
1008:
1009:
1010: RectangularShape rect = new Ellipse2D.Double();
1011:
1012:
1013:
1014: Object antiAlias = g2.getRenderingHint(RenderingHints.KEY_ANTIALIASING);
1015: g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
1016: RenderingHints.VALUE_ANTIALIAS_OFF);
1017:
1018:
1019:
1020: Number[] xNumber = data.getXValues();
1021: Number[] yNumber = data.getYValues();
1022: Number[] zNumber = data.getZValues();
1023:
1024: double[] x = new double[xNumber.length];
1025: double[] y = new double[yNumber.length];
1026:
1027: for (int i = 0; i < x.length; i++) {
1028: x[i] = xNumber[i].doubleValue();
1029: y[i] = yNumber[i].doubleValue();
1030: }
1031:
1032: double transX = 0.0;
1033: double transDX = 0.0;
1034: double transY = 0.0;
1035: double transDY = 0.0;
1036: double size = dataArea.getWidth() * this.ptSizePct;
1037: for (int k = 0; k < x.length; k++) {
1038:
1039: transX = domainAxis.valueToJava2D(x[k], dataArea,
1040: RectangleEdge.BOTTOM) - 0.5 * size;
1041: transY = rangeAxis.valueToJava2D(y[k], dataArea, RectangleEdge.LEFT)
1042: - 0.5 * size;
1043: transDX = size;
1044: transDY = size;
1045:
1046: rect.setFrame(transX, transY, transDX, transDY);
1047:
1048: if (zNumber[k] != null) {
1049: g2.setPaint(colorBar.getPaint(zNumber[k].doubleValue()));
1050: g2.fill(rect);
1051: }
1052: else if (this.missingPaint != null) {
1053: g2.setPaint(this.missingPaint);
1054: g2.fill(rect);
1055: }
1056:
1057:
1058: entityArea = rect;
1059:
1060:
1061: if (entities != null) {
1062: String tip = null;
1063: if (getToolTipGenerator() != null) {
1064: tip = this.toolTipGenerator.generateToolTip(data, k);
1065: }
1066: String url = null;
1067:
1068:
1069:
1070:
1071:
1072: ContourEntity entity = new ContourEntity(
1073: (RectangularShape) entityArea.clone(), tip, url);
1074: entity.setIndex(k);
1075: entities.add(entity);
1076: }
1077:
1078:
1079: if (plot.isDomainCrosshairLockedOnData()) {
1080: if (plot.isRangeCrosshairLockedOnData()) {
1081:
1082: crosshairState.updateCrosshairPoint(x[k], y[k], transX,
1083: transY, PlotOrientation.VERTICAL);
1084: }
1085: else {
1086:
1087: crosshairState.updateCrosshairX(transX);
1088: }
1089: }
1090: else {
1091: if (plot.isRangeCrosshairLockedOnData()) {
1092:
1093: crosshairState.updateCrosshairY(transY);
1094: }
1095: }
1096: }
1097:
1098:
1099: g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, antiAlias);
1100:
1101: return;
1102:
1103: }
1104:
1105:
1114: protected void drawVerticalLine(Graphics2D g2, Rectangle2D dataArea,
1115: double value, Stroke stroke, Paint paint) {
1116:
1117: double xx = getDomainAxis().valueToJava2D(value, dataArea,
1118: RectangleEdge.BOTTOM);
1119: Line2D line = new Line2D.Double(xx, dataArea.getMinY(), xx,
1120: dataArea.getMaxY());
1121: g2.setStroke(stroke);
1122: g2.setPaint(paint);
1123: g2.draw(line);
1124:
1125: }
1126:
1127:
1136: protected void drawHorizontalLine(Graphics2D g2, Rectangle2D dataArea,
1137: double value, Stroke stroke,
1138: Paint paint) {
1139:
1140: double yy = getRangeAxis().valueToJava2D(value, dataArea,
1141: RectangleEdge.LEFT);
1142: Line2D line = new Line2D.Double(dataArea.getMinX(), yy,
1143: dataArea.getMaxX(), yy);
1144: g2.setStroke(stroke);
1145: g2.setPaint(paint);
1146: g2.draw(line);
1147:
1148: }
1149:
1150:
1157: public void handleClick(int x, int y, PlotRenderingInfo info) {
1158:
1159:
1180: }
1181:
1182:
1187: public void zoom(double percent) {
1188:
1189: if (percent > 0) {
1190:
1191:
1192:
1193:
1194:
1195:
1196:
1197: }
1198: else {
1199: getRangeAxis().setAutoRange(true);
1200: getDomainAxis().setAutoRange(true);
1201: }
1202:
1203: }
1204:
1205:
1210: public String getPlotType() {
1211: return localizationResources.getString("Contour_Plot");
1212: }
1213:
1214:
1221: public Range getDataRange(ValueAxis axis) {
1222:
1223: if (this.dataset == null) {
1224: return null;
1225: }
1226:
1227: Range result = null;
1228:
1229: if (axis == getDomainAxis()) {
1230: result = DatasetUtilities.findDomainBounds(this.dataset);
1231: }
1232: else if (axis == getRangeAxis()) {
1233: result = DatasetUtilities.findRangeBounds(this.dataset);
1234: }
1235:
1236: return result;
1237:
1238: }
1239:
1240:
1245: public Range getContourDataRange() {
1246:
1247: Range result = null;
1248:
1249: ContourDataset data = getDataset();
1250:
1251: if (data != null) {
1252: Range h = getDomainAxis().getRange();
1253: Range v = getRangeAxis().getRange();
1254: result = this.visibleRange(data, h, v);
1255: }
1256:
1257: return result;
1258: }
1259:
1260:
1267: public void propertyChange(PropertyChangeEvent event) {
1268: notifyListeners(new PlotChangeEvent(this));
1269: }
1270:
1271:
1279: public void datasetChanged(DatasetChangeEvent event) {
1280: if (this.domainAxis != null) {
1281: this.domainAxis.configure();
1282: }
1283: if (this.rangeAxis != null) {
1284: this.rangeAxis.configure();
1285: }
1286: if (this.colorBar != null) {
1287: this.colorBar.configure(this);
1288: }
1289: super.datasetChanged(event);
1290: }
1291:
1292:
1297: public ColorBar getColorBar() {
1298: return this.colorBar;
1299: }
1300:
1301:
1306: public boolean isDomainCrosshairVisible() {
1307: return this.domainCrosshairVisible;
1308: }
1309:
1310:
1315: public void setDomainCrosshairVisible(boolean flag) {
1316:
1317: if (this.domainCrosshairVisible != flag) {
1318: this.domainCrosshairVisible = flag;
1319: notifyListeners(new PlotChangeEvent(this));
1320: }
1321:
1322: }
1323:
1324:
1330: public boolean isDomainCrosshairLockedOnData() {
1331: return this.domainCrosshairLockedOnData;
1332: }
1333:
1334:
1340: public void setDomainCrosshairLockedOnData(boolean flag) {
1341: if (this.domainCrosshairLockedOnData != flag) {
1342: this.domainCrosshairLockedOnData = flag;
1343: notifyListeners(new PlotChangeEvent(this));
1344: }
1345: }
1346:
1347:
1352: public double getDomainCrosshairValue() {
1353: return this.domainCrosshairValue;
1354: }
1355:
1356:
1364: public void setDomainCrosshairValue(double value) {
1365: setDomainCrosshairValue(value, true);
1366: }
1367:
1368:
1378: public void setDomainCrosshairValue(double value, boolean notify) {
1379: this.domainCrosshairValue = value;
1380: if (isDomainCrosshairVisible() && notify) {
1381: notifyListeners(new PlotChangeEvent(this));
1382: }
1383: }
1384:
1385:
1390: public Stroke getDomainCrosshairStroke() {
1391: return this.domainCrosshairStroke;
1392: }
1393:
1394:
1400: public void setDomainCrosshairStroke(Stroke stroke) {
1401: this.domainCrosshairStroke = stroke;
1402: notifyListeners(new PlotChangeEvent(this));
1403: }
1404:
1405:
1410: public Paint getDomainCrosshairPaint() {
1411: return this.domainCrosshairPaint;
1412: }
1413:
1414:
1420: public void setDomainCrosshairPaint(Paint paint) {
1421: this.domainCrosshairPaint = paint;
1422: notifyListeners(new PlotChangeEvent(this));
1423: }
1424:
1425:
1430: public boolean isRangeCrosshairVisible() {
1431: return this.rangeCrosshairVisible;
1432: }
1433:
1434:
1439: public void setRangeCrosshairVisible(boolean flag) {
1440: if (this.rangeCrosshairVisible != flag) {
1441: this.rangeCrosshairVisible = flag;
1442: notifyListeners(new PlotChangeEvent(this));
1443: }
1444: }
1445:
1446:
1452: public boolean isRangeCrosshairLockedOnData() {
1453: return this.rangeCrosshairLockedOnData;
1454: }
1455:
1456:
1462: public void setRangeCrosshairLockedOnData(boolean flag) {
1463: if (this.rangeCrosshairLockedOnData != flag) {
1464: this.rangeCrosshairLockedOnData = flag;
1465: notifyListeners(new PlotChangeEvent(this));
1466: }
1467: }
1468:
1469:
1474: public double getRangeCrosshairValue() {
1475: return this.rangeCrosshairValue;
1476: }
1477:
1478:
1486: public void setRangeCrosshairValue(double value) {
1487: setRangeCrosshairValue(value, true);
1488: }
1489:
1490:
1500: public void setRangeCrosshairValue(double value, boolean notify) {
1501: this.rangeCrosshairValue = value;
1502: if (isRangeCrosshairVisible() && notify) {
1503: notifyListeners(new PlotChangeEvent(this));
1504: }
1505: }
1506:
1507:
1512: public Stroke getRangeCrosshairStroke() {
1513: return this.rangeCrosshairStroke;
1514: }
1515:
1516:
1522: public void setRangeCrosshairStroke(Stroke stroke) {
1523: this.rangeCrosshairStroke = stroke;
1524: notifyListeners(new PlotChangeEvent(this));
1525: }
1526:
1527:
1532: public Paint getRangeCrosshairPaint() {
1533: return this.rangeCrosshairPaint;
1534: }
1535:
1536:
1542: public void setRangeCrosshairPaint(Paint paint) {
1543: this.rangeCrosshairPaint = paint;
1544: notifyListeners(new PlotChangeEvent(this));
1545: }
1546:
1547:
1552: public ContourToolTipGenerator getToolTipGenerator() {
1553: return this.toolTipGenerator;
1554: }
1555:
1556:
1561: public void setToolTipGenerator(ContourToolTipGenerator generator) {
1562:
1563: this.toolTipGenerator = generator;
1564: }
1565:
1566:
1571: public XYURLGenerator getURLGenerator() {
1572: return this.urlGenerator;
1573: }
1574:
1575:
1580: public void setURLGenerator(XYURLGenerator urlGenerator) {
1581:
1582: this.urlGenerator = urlGenerator;
1583: }
1584:
1585:
1594: public void drawDomainMarker(Graphics2D g2,
1595: ContourPlot plot,
1596: ValueAxis domainAxis,
1597: Marker marker,
1598: Rectangle2D dataArea) {
1599:
1600: if (marker instanceof ValueMarker) {
1601: ValueMarker vm = (ValueMarker) marker;
1602: double value = vm.getValue();
1603: Range range = domainAxis.getRange();
1604: if (!range.contains(value)) {
1605: return;
1606: }
1607:
1608: double x = domainAxis.valueToJava2D(value, dataArea,
1609: RectangleEdge.BOTTOM);
1610: Line2D line = new Line2D.Double(x, dataArea.getMinY(), x,
1611: dataArea.getMaxY());
1612: Paint paint = marker.getOutlinePaint();
1613: Stroke stroke = marker.getOutlineStroke();
1614: g2.setPaint(paint != null ? paint : Plot.DEFAULT_OUTLINE_PAINT);
1615: g2.setStroke(stroke != null ? stroke : Plot.DEFAULT_OUTLINE_STROKE);
1616: g2.draw(line);
1617: }
1618:
1619: }
1620:
1621:
1630: public void drawRangeMarker(Graphics2D g2,
1631: ContourPlot plot,
1632: ValueAxis rangeAxis,
1633: Marker marker,
1634: Rectangle2D dataArea) {
1635:
1636: if (marker instanceof ValueMarker) {
1637: ValueMarker vm = (ValueMarker) marker;
1638: double value = vm.getValue();
1639: Range range = rangeAxis.getRange();
1640: if (!range.contains(value)) {
1641: return;
1642: }
1643:
1644: double y = rangeAxis.valueToJava2D(value, dataArea,
1645: RectangleEdge.LEFT);
1646: Line2D line = new Line2D.Double(dataArea.getMinX(), y,
1647: dataArea.getMaxX(), y);
1648: Paint paint = marker.getOutlinePaint();
1649: Stroke stroke = marker.getOutlineStroke();
1650: g2.setPaint(paint != null ? paint : Plot.DEFAULT_OUTLINE_PAINT);
1651: g2.setStroke(stroke != null ? stroke : Plot.DEFAULT_OUTLINE_STROKE);
1652: g2.draw(line);
1653: }
1654:
1655: }
1656:
1657:
1661: public ClipPath getClipPath() {
1662: return this.clipPath;
1663: }
1664:
1665:
1669: public void setClipPath(ClipPath clipPath) {
1670: this.clipPath = clipPath;
1671: }
1672:
1673:
1677: public double getPtSizePct() {
1678: return this.ptSizePct;
1679: }
1680:
1681:
1685: public boolean isRenderAsPoints() {
1686: return this.renderAsPoints;
1687: }
1688:
1689:
1693: public void setPtSizePct(double ptSizePct) {
1694: this.ptSizePct = ptSizePct;
1695: }
1696:
1697:
1701: public void setRenderAsPoints(boolean renderAsPoints) {
1702: this.renderAsPoints = renderAsPoints;
1703: }
1704:
1705:
1710: public void axisChanged(AxisChangeEvent event) {
1711: Object source = event.getSource();
1712: if (source.equals(this.rangeAxis) || source.equals(this.domainAxis)) {
1713: ColorBar cba = this.colorBar;
1714: if (this.colorBar.getAxis().isAutoRange()) {
1715: cba.getAxis().configure();
1716: }
1717:
1718: }
1719: super.axisChanged(event);
1720: }
1721:
1722:
1731: public Range visibleRange(ContourDataset data, Range x, Range y) {
1732: Range range = null;
1733: range = data.getZValueRange(x, y);
1734: return range;
1735: }
1736:
1737:
1741: public Paint getMissingPaint() {
1742: return this.missingPaint;
1743: }
1744:
1745:
1750: public void setMissingPaint(Paint paint) {
1751: this.missingPaint = paint;
1752: }
1753:
1754:
1762: public void zoomDomainAxes(double x, double y, double factor) {
1763:
1764: }
1765:
1766:
1774: public void zoomDomainAxes(double x, double y, double lowerPercent,
1775: double upperPercent) {
1776:
1777: }
1778:
1779:
1786: public void zoomRangeAxes(double x, double y, double factor) {
1787:
1788: }
1789:
1790:
1798: public void zoomRangeAxes(double x, double y, double lowerPercent,
1799: double upperPercent) {
1800:
1801: }
1802:
1803:
1808: public boolean isDomainZoomable() {
1809: return false;
1810: }
1811:
1812:
1817: public boolean isRangeZoomable() {
1818: return false;
1819: }
1820:
1821:
1825: public Object clone() throws CloneNotSupportedException {
1826: ContourPlot clone = (ContourPlot) super.clone();
1827:
1828: if (this.domainAxis != null) {
1829: clone.domainAxis = (ValueAxis) this.domainAxis.clone();
1830: clone.domainAxis.setPlot(clone);
1831: clone.domainAxis.addChangeListener(clone);
1832: }
1833: if (this.rangeAxis != null) {
1834: clone.rangeAxis = (ValueAxis) this.rangeAxis.clone();
1835: clone.rangeAxis.setPlot(clone);
1836: clone.rangeAxis.addChangeListener(clone);
1837: }
1838:
1839: if (clone.dataset != null) {
1840: clone.dataset.addChangeListener(clone);
1841: }
1842:
1843: if (this.colorBar != null) {
1844: clone.colorBar = (ColorBar) this.colorBar.clone();
1845: }
1846:
1847: clone.domainMarkers = (List) ObjectUtilities.deepClone(
1848: this.domainMarkers);
1849: clone.rangeMarkers = (List) ObjectUtilities.deepClone(
1850: this.rangeMarkers);
1851: clone.annotations = (List) ObjectUtilities.deepClone(this.annotations);
1852:
1853: if (this.clipPath != null) {
1854: clone.clipPath = (ClipPath) this.clipPath.clone();
1855: }
1856:
1857: return clone;
1858: }
1859:
1860: }