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:
111:
116: public class ContourPlot extends Plot implements ContourValuePlot,
117: ValueAxisPlot,
118: PropertyChangeListener,
119: Serializable,
120: Cloneable {
121:
122:
123: private static final long serialVersionUID = 7861072556590502247L;
124:
125:
126: protected static final RectangleInsets DEFAULT_INSETS
127: = new RectangleInsets(2.0, 2.0, 100.0, 10.0);
128:
129:
130: private ValueAxis domainAxis;
131:
132:
133: private ValueAxis rangeAxis;
134:
135:
136: private ContourDataset dataset;
137:
138:
139: private ColorBar colorBar = null;
140:
141:
142: private RectangleEdge colorBarLocation;
143:
144:
145: private boolean domainCrosshairVisible;
146:
147:
148: private double domainCrosshairValue;
149:
150:
151: private transient Stroke domainCrosshairStroke;
152:
153:
154: private transient Paint domainCrosshairPaint;
155:
156:
160: private boolean domainCrosshairLockedOnData = true;
161:
162:
163: private boolean rangeCrosshairVisible;
164:
165:
166: private double rangeCrosshairValue;
167:
168:
169: private transient Stroke rangeCrosshairStroke;
170:
171:
172: private transient Paint rangeCrosshairPaint;
173:
174:
178: private boolean rangeCrosshairLockedOnData = true;
179:
180:
189: private double dataAreaRatio = 0.0;
190:
191:
192: private List domainMarkers;
193:
194:
195: private List rangeMarkers;
196:
197:
198: private List annotations;
199:
200:
201: private ContourToolTipGenerator toolTipGenerator;
202:
203:
204: private XYURLGenerator urlGenerator;
205:
206:
210: private boolean renderAsPoints = false;
211:
212:
216: private double ptSizePct = 0.05;
217:
218:
219: private transient ClipPath clipPath = null;
220:
221:
222: private transient Paint missingPaint = null;
223:
224:
225: protected static ResourceBundle localizationResources =
226: ResourceBundle.getBundle("org.jfree.chart.plot.LocalizationBundle");
227:
228:
231: public ContourPlot() {
232: this(null, null, null, null);
233: }
234:
235:
244: public ContourPlot(ContourDataset dataset,
245: ValueAxis domainAxis, ValueAxis rangeAxis,
246: ColorBar colorBar) {
247:
248: super();
249:
250: this.dataset = dataset;
251: if (dataset != null) {
252: dataset.addChangeListener(this);
253: }
254:
255: this.domainAxis = domainAxis;
256: if (domainAxis != null) {
257: domainAxis.setPlot(this);
258: domainAxis.addChangeListener(this);
259: }
260:
261: this.rangeAxis = rangeAxis;
262: if (rangeAxis != null) {
263: rangeAxis.setPlot(this);
264: rangeAxis.addChangeListener(this);
265: }
266:
267: this.colorBar = colorBar;
268: if (colorBar != null) {
269: colorBar.getAxis().setPlot(this);
270: colorBar.getAxis().addChangeListener(this);
271: colorBar.configure(this);
272: }
273: this.colorBarLocation = RectangleEdge.LEFT;
274:
275: this.toolTipGenerator = new StandardContourToolTipGenerator();
276:
277: }
278:
279:
284: public RectangleEdge getColorBarLocation() {
285: return this.colorBarLocation;
286: }
287:
288:
294: public void setColorBarLocation(RectangleEdge edge) {
295: this.colorBarLocation = edge;
296: notifyListeners(new PlotChangeEvent(this));
297: }
298:
299:
304: public ContourDataset getDataset() {
305: return this.dataset;
306: }
307:
308:
314: public void setDataset(ContourDataset dataset) {
315:
316:
317:
318: ContourDataset existing = this.dataset;
319: if (existing != null) {
320: existing.removeChangeListener(this);
321: }
322:
323:
324: this.dataset = dataset;
325: if (dataset != null) {
326: setDatasetGroup(dataset.getGroup());
327: dataset.addChangeListener(this);
328: }
329:
330:
331: DatasetChangeEvent event = new DatasetChangeEvent(this, dataset);
332: datasetChanged(event);
333:
334: }
335:
336:
341: public ValueAxis getDomainAxis() {
342:
343: ValueAxis result = this.domainAxis;
344:
345: return result;
346:
347: }
348:
349:
355: public void setDomainAxis(ValueAxis axis) {
356:
357: if (isCompatibleDomainAxis(axis)) {
358:
359: if (axis != null) {
360: axis.setPlot(this);
361: axis.addChangeListener(this);
362: }
363:
364:
365: if (this.domainAxis != null) {
366: this.domainAxis.removeChangeListener(this);
367: }
368:
369: this.domainAxis = axis;
370: notifyListeners(new PlotChangeEvent(this));
371:
372: }
373:
374: }
375:
376:
381: public ValueAxis getRangeAxis() {
382:
383: ValueAxis result = this.rangeAxis;
384:
385: return result;
386:
387: }
388:
389:
397: public void setRangeAxis(ValueAxis axis) {
398:
399: if (axis != null) {
400: axis.setPlot(this);
401: axis.addChangeListener(this);
402: }
403:
404:
405: if (this.rangeAxis != null) {
406: this.rangeAxis.removeChangeListener(this);
407: }
408:
409: this.rangeAxis = axis;
410: notifyListeners(new PlotChangeEvent(this));
411:
412: }
413:
414:
419: public void setColorBarAxis(ColorBar axis) {
420:
421: this.colorBar = axis;
422: notifyListeners(new PlotChangeEvent(this));
423:
424: }
425:
426:
431: public double getDataAreaRatio() {
432: return this.dataAreaRatio;
433: }
434:
435:
440: public void setDataAreaRatio(double ratio) {
441: this.dataAreaRatio = ratio;
442: }
443:
444:
452: public void addDomainMarker(Marker marker) {
453:
454: if (this.domainMarkers == null) {
455: this.domainMarkers = new java.util.ArrayList();
456: }
457: this.domainMarkers.add(marker);
458: notifyListeners(new PlotChangeEvent(this));
459:
460: }
461:
462:
465: public void clearDomainMarkers() {
466: if (this.domainMarkers != null) {
467: this.domainMarkers.clear();
468: notifyListeners(new PlotChangeEvent(this));
469: }
470: }
471:
472:
480: public void addRangeMarker(Marker marker) {
481:
482: if (this.rangeMarkers == null) {
483: this.rangeMarkers = new java.util.ArrayList();
484: }
485: this.rangeMarkers.add(marker);
486: notifyListeners(new PlotChangeEvent(this));
487:
488: }
489:
490:
493: public void clearRangeMarkers() {
494: if (this.rangeMarkers != null) {
495: this.rangeMarkers.clear();
496: notifyListeners(new PlotChangeEvent(this));
497: }
498: }
499:
500:
505: public void addAnnotation(XYAnnotation annotation) {
506:
507: if (this.annotations == null) {
508: this.annotations = new java.util.ArrayList();
509: }
510: this.annotations.add(annotation);
511: notifyListeners(new PlotChangeEvent(this));
512:
513: }
514:
515:
518: public void clearAnnotations() {
519: if (this.annotations != null) {
520: this.annotations.clear();
521: notifyListeners(new PlotChangeEvent(this));
522: }
523: }
524:
525:
533: public boolean isCompatibleDomainAxis(ValueAxis axis) {
534:
535: return true;
536:
537: }
538:
539:
555: public void draw(Graphics2D g2, Rectangle2D area, Point2D anchor,
556: PlotState parentState,
557: PlotRenderingInfo info) {
558:
559:
560: boolean b1 = (area.getWidth() <= MINIMUM_WIDTH_TO_DRAW);
561: boolean b2 = (area.getHeight() <= MINIMUM_HEIGHT_TO_DRAW);
562: if (b1 || b2) {
563: return;
564: }
565:
566:
567: if (info != null) {
568: info.setPlotArea(area);
569: }
570:
571:
572: RectangleInsets insets = getInsets();
573: insets.trim(area);
574:
575: AxisSpace space = new AxisSpace();
576:
577: space = this.domainAxis.reserveSpace(
578: g2, this, area, RectangleEdge.BOTTOM, space
579: );
580: space = this.rangeAxis.reserveSpace(
581: g2, this, area, RectangleEdge.LEFT, space
582: );
583:
584: Rectangle2D estimatedDataArea = space.shrink(area, null);
585:
586: AxisSpace space2 = new AxisSpace();
587: space2 = this.colorBar.reserveSpace(
588: g2, this, area, estimatedDataArea, this.colorBarLocation,
589: space2
590: );
591: Rectangle2D adjustedPlotArea = space2.shrink(area, null);
592:
593: Rectangle2D dataArea = space.shrink(adjustedPlotArea, null);
594:
595: Rectangle2D colorBarArea = space2.reserved(
596: area, this.colorBarLocation
597: );
598:
599:
600: if (getDataAreaRatio() != 0.0) {
601: double ratio = getDataAreaRatio();
602: Rectangle2D tmpDataArea = (Rectangle2D) dataArea.clone();
603: double h = tmpDataArea.getHeight();
604: double w = tmpDataArea.getWidth();
605:
606: if (ratio > 0) {
607: if (w * ratio <= h) {
608: h = ratio * w;
609: }
610: else {
611: w = h / ratio;
612: }
613: }
614: else {
615: ratio *= -1.0;
616: double xLength = getDomainAxis().getRange().getLength();
617: double yLength = getRangeAxis().getRange().getLength();
618: double unitRatio = yLength / xLength;
619:
620: ratio = unitRatio * ratio;
621:
622: if (w * ratio <= h) {
623: h = ratio * w;
624: }
625: else {
626: w = h / ratio;
627: }
628: }
629:
630: dataArea.setRect(
631: tmpDataArea.getX() + tmpDataArea.getWidth() / 2 - w / 2,
632: tmpDataArea.getY(), w, h
633: );
634: }
635:
636: if (info != null) {
637: info.setDataArea(dataArea);
638: }
639:
640: CrosshairState crosshairState = new CrosshairState();
641: crosshairState.setCrosshairDistance(Double.POSITIVE_INFINITY);
642:
643:
644: drawBackground(g2, dataArea);
645:
646: double cursor = dataArea.getMaxY();
647: if (this.domainAxis != null) {
648: this.domainAxis.draw(
649: g2, cursor, adjustedPlotArea, dataArea, RectangleEdge.BOTTOM,
650: info
651: );
652: }
653:
654: if (this.rangeAxis != null) {
655: cursor = dataArea.getMinX();
656: this.rangeAxis.draw(
657: g2, cursor, adjustedPlotArea, dataArea, RectangleEdge.LEFT, info
658: );
659: }
660:
661: if (this.colorBar != null) {
662: cursor = 0.0;
663: cursor = this.colorBar.draw(
664: g2, cursor, adjustedPlotArea, dataArea, colorBarArea,
665: this.colorBarLocation
666: );
667: }
668: Shape originalClip = g2.getClip();
669: Composite originalComposite = g2.getComposite();
670:
671: g2.clip(dataArea);
672: g2.setComposite(AlphaComposite.getInstance(
673: AlphaComposite.SRC_OVER, getForegroundAlpha())
674: );
675: render(g2, dataArea, info, crosshairState);
676:
677: if (this.domainMarkers != null) {
678: Iterator iterator = this.domainMarkers.iterator();
679: while (iterator.hasNext()) {
680: Marker marker = (Marker) iterator.next();
681: drawDomainMarker(g2, this, getDomainAxis(), marker, dataArea);
682: }
683: }
684:
685: if (this.rangeMarkers != null) {
686: Iterator iterator = this.rangeMarkers.iterator();
687: while (iterator.hasNext()) {
688: Marker marker = (Marker) iterator.next();
689: drawRangeMarker(g2, this, getRangeAxis(), marker, dataArea);
690: }
691: }
692:
693:
694:
695:
696:
697:
698:
699:
700:
701:
702:
703:
704:
705:
706:
707:
708:
709:
710: g2.setClip(originalClip);
711: g2.setComposite(originalComposite);
712: drawOutline(g2, dataArea);
713:
714: }
715:
716:
728: public void render(Graphics2D g2, Rectangle2D dataArea,
729: PlotRenderingInfo info, CrosshairState crosshairState) {
730:
731:
732:
733: ContourDataset data = getDataset();
734: if (data != null) {
735:
736: ColorBar zAxis = getColorBar();
737:
738: if (this.clipPath != null) {
739: GeneralPath clipper = getClipPath().draw(
740: g2, dataArea, this.domainAxis, this.rangeAxis
741: );
742: if (this.clipPath.isClip()) {
743: g2.clip(clipper);
744: }
745: }
746:
747: if (this.renderAsPoints) {
748: pointRenderer(g2, dataArea, info, this,
749: this.domainAxis, this.rangeAxis, zAxis,
750: data, crosshairState);
751: }
752: else {
753: contourRenderer(g2, dataArea, info, this,
754: this.domainAxis, this.rangeAxis, zAxis,
755: data, crosshairState);
756: }
757:
758:
759: setDomainCrosshairValue(crosshairState.getCrosshairX(), false);
760: if (isDomainCrosshairVisible()) {
761: drawVerticalLine(g2, dataArea,
762: getDomainCrosshairValue(),
763: getDomainCrosshairStroke(),
764: getDomainCrosshairPaint());
765: }
766:
767:
768: setRangeCrosshairValue(crosshairState.getCrosshairY(), false);
769: if (isRangeCrosshairVisible()) {
770: drawHorizontalLine(g2, dataArea,
771: getRangeCrosshairValue(),
772: getRangeCrosshairStroke(),
773: getRangeCrosshairPaint());
774: }
775:
776: }
777: else if (this.clipPath != null) {
778: getClipPath().draw(g2, dataArea, this.domainAxis, this.rangeAxis);
779: }
780:
781: }
782:
783:
797: public void contourRenderer(Graphics2D g2,
798: Rectangle2D dataArea,
799: PlotRenderingInfo info,
800: ContourPlot plot,
801: ValueAxis horizontalAxis,
802: ValueAxis verticalAxis,
803: ColorBar colorBar,
804: ContourDataset data,
805: CrosshairState crosshairState) {
806:
807:
808: Rectangle2D.Double entityArea = null;
809: EntityCollection entities = null;
810: if (info != null) {
811: entities = info.getOwner().getEntityCollection();
812: }
813:
814: Rectangle2D.Double rect = null;
815: rect = new Rectangle2D.Double();
816:
817:
818: Object antiAlias = g2.getRenderingHint(RenderingHints.KEY_ANTIALIASING);
819: g2.setRenderingHint(
820: RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF
821: );
822:
823:
824: Number[] xNumber = data.getXValues();
825: Number[] yNumber = data.getYValues();
826: Number[] zNumber = data.getZValues();
827:
828: double[] x = new double[xNumber.length];
829: double[] y = new double[yNumber.length];
830:
831: for (int i = 0; i < x.length; i++) {
832: x[i] = xNumber[i].doubleValue();
833: y[i] = yNumber[i].doubleValue();
834: }
835:
836: int[] xIndex = data.indexX();
837: int[] indexX = data.getXIndices();
838: boolean vertInverted = ((NumberAxis) verticalAxis).isInverted();
839: boolean horizInverted = false;
840: if (horizontalAxis instanceof NumberAxis) {
841: horizInverted = ((NumberAxis) horizontalAxis).isInverted();
842: }
843: double transX = 0.0;
844: double transXm1 = 0.0;
845: double transXp1 = 0.0;
846: double transDXm1 = 0.0;
847: double transDXp1 = 0.0;
848: double transDX = 0.0;
849: double transY = 0.0;
850: double transYm1 = 0.0;
851: double transYp1 = 0.0;
852: double transDYm1 = 0.0;
853: double transDYp1 = 0.0;
854: double transDY = 0.0;
855: int iMax = xIndex[xIndex.length - 1];
856: for (int k = 0; k < x.length; k++) {
857: int i = xIndex[k];
858: if (indexX[i] == k) {
859: if (i == 0) {
860: transX = horizontalAxis.valueToJava2D(
861: x[k], dataArea, RectangleEdge.BOTTOM
862: );
863: transXm1 = transX;
864: transXp1 = horizontalAxis.valueToJava2D(
865: x[indexX[i + 1]], dataArea, RectangleEdge.BOTTOM
866: );
867: transDXm1 = Math.abs(0.5 * (transX - transXm1));
868: transDXp1 = Math.abs(0.5 * (transX - transXp1));
869: }
870: else if (i == iMax) {
871: transX = horizontalAxis.valueToJava2D(
872: x[k], dataArea, RectangleEdge.BOTTOM
873: );
874: transXm1 = horizontalAxis.valueToJava2D(
875: x[indexX[i - 1]], dataArea, RectangleEdge.BOTTOM
876: );
877: transXp1 = transX;
878: transDXm1 = Math.abs(0.5 * (transX - transXm1));
879: transDXp1 = Math.abs(0.5 * (transX - transXp1));
880: }
881: else {
882: transX = horizontalAxis.valueToJava2D(
883: x[k], dataArea, RectangleEdge.BOTTOM
884: );
885: transXp1 = horizontalAxis.valueToJava2D(
886: x[indexX[i + 1]], dataArea, RectangleEdge.BOTTOM
887: );
888: transDXm1 = transDXp1;
889: transDXp1 = Math.abs(0.5 * (transX - transXp1));
890: }
891:
892: if (horizInverted) {
893: transX -= transDXp1;
894: }
895: else {
896: transX -= transDXm1;
897: }
898:
899: transDX = transDXm1 + transDXp1;
900:
901: transY = verticalAxis.valueToJava2D(
902: y[k], dataArea, RectangleEdge.LEFT
903: );
904: transYm1 = transY;
905: if (k + 1 == y.length) {
906: continue;
907: }
908: transYp1 = verticalAxis.valueToJava2D(
909: y[k + 1], dataArea, RectangleEdge.LEFT
910: );
911: transDYm1 = Math.abs(0.5 * (transY - transYm1));
912: transDYp1 = Math.abs(0.5 * (transY - transYp1));
913: }
914: else if ((i < indexX.length - 1
915: && indexX[i + 1] - 1 == k) || k == x.length - 1) {
916:
917: transY = verticalAxis.valueToJava2D(
918: y[k], dataArea, RectangleEdge.LEFT
919: );
920: transYm1 = verticalAxis.valueToJava2D(
921: y[k - 1], dataArea, RectangleEdge.LEFT
922: );
923: transYp1 = transY;
924: transDYm1 = Math.abs(0.5 * (transY - transYm1));
925: transDYp1 = Math.abs(0.5 * (transY - transYp1));
926: }
927: else {
928: transY = verticalAxis.valueToJava2D(
929: y[k], dataArea, RectangleEdge.LEFT
930: );
931: transYp1 = verticalAxis.valueToJava2D(
932: y[k + 1], dataArea, RectangleEdge.LEFT
933: );
934: transDYm1 = transDYp1;
935: transDYp1 = Math.abs(0.5 * (transY - transYp1));
936: }
937: if (vertInverted) {
938: transY -= transDYm1;
939: }
940: else {
941: transY -= transDYp1;
942: }
943:
944: transDY = transDYm1 + transDYp1;
945:
946: rect.setRect(transX, transY, transDX, transDY);
947: if (zNumber[k] != null) {
948: g2.setPaint(colorBar.getPaint(zNumber[k].doubleValue()));
949: g2.fill(rect);
950: }
951: else if (this.missingPaint != null) {
952: g2.setPaint(this.missingPaint);
953: g2.fill(rect);
954: }
955:
956: entityArea = rect;
957:
958:
959: if (entities != null) {
960: String tip = "";
961: if (getToolTipGenerator() != null) {
962: tip = this.toolTipGenerator.generateToolTip(data, k);
963: }
964:
965:
966: String url = null;
967:
968:
969:
970:
971:
972: ContourEntity entity = new ContourEntity(
973: (Rectangle2D.Double) entityArea.clone(), tip, url
974: );
975: entity.setIndex(k);
976: entities.add(entity);
977:
978: }
979:
980:
981: if (plot.isDomainCrosshairLockedOnData()) {
982: if (plot.isRangeCrosshairLockedOnData()) {
983:
984: crosshairState.updateCrosshairPoint(
985: x[k], y[k], transX, transY, PlotOrientation.VERTICAL
986: );
987: }
988: else {
989:
990: crosshairState.updateCrosshairX(transX);
991: }
992: }
993: else {
994: if (plot.isRangeCrosshairLockedOnData()) {
995:
996: crosshairState.updateCrosshairY(transY);
997: }
998: }
999: }
1000:
1001: g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, antiAlias);
1002:
1003: return;
1004:
1005: }
1006:
1007:
1021: public void pointRenderer(Graphics2D g2,
1022: Rectangle2D dataArea,
1023: PlotRenderingInfo info,
1024: ContourPlot plot,
1025: ValueAxis domainAxis,
1026: ValueAxis rangeAxis,
1027: ColorBar colorBar,
1028: ContourDataset data,
1029: CrosshairState crosshairState) {
1030:
1031:
1032: RectangularShape entityArea = null;
1033: EntityCollection entities = null;
1034: if (info != null) {
1035: entities = info.getOwner().getEntityCollection();
1036: }
1037:
1038:
1039:
1040: RectangularShape rect = new Ellipse2D.Double();
1041:
1042:
1043:
1044: Object antiAlias = g2.getRenderingHint(RenderingHints.KEY_ANTIALIASING);
1045: g2.setRenderingHint(
1046: RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF
1047: );
1048:
1049:
1050:
1051: Number[] xNumber = data.getXValues();
1052: Number[] yNumber = data.getYValues();
1053: Number[] zNumber = data.getZValues();
1054:
1055: double[] x = new double[xNumber.length];
1056: double[] y = new double[yNumber.length];
1057:
1058: for (int i = 0; i < x.length; i++) {
1059: x[i] = xNumber[i].doubleValue();
1060: y[i] = yNumber[i].doubleValue();
1061: }
1062:
1063: double transX = 0.0;
1064: double transDX = 0.0;
1065: double transY = 0.0;
1066: double transDY = 0.0;
1067: double size = dataArea.getWidth() * this.ptSizePct;
1068: for (int k = 0; k < x.length; k++) {
1069:
1070: transX = domainAxis.valueToJava2D(
1071: x[k], dataArea, RectangleEdge.BOTTOM
1072: ) - 0.5 * size;
1073: transY = rangeAxis.valueToJava2D(y[k], dataArea, RectangleEdge.LEFT)
1074: - 0.5 * size;
1075: transDX = size;
1076: transDY = size;
1077:
1078: rect.setFrame(transX, transY, transDX, transDY);
1079:
1080: if (zNumber[k] != null) {
1081: g2.setPaint(colorBar.getPaint(zNumber[k].doubleValue()));
1082: g2.fill(rect);
1083: }
1084: else if (this.missingPaint != null) {
1085: g2.setPaint(this.missingPaint);
1086: g2.fill(rect);
1087: }
1088:
1089:
1090: entityArea = rect;
1091:
1092:
1093: if (entities != null) {
1094: String tip = null;
1095: if (getToolTipGenerator() != null) {
1096: tip = this.toolTipGenerator.generateToolTip(data, k);
1097: }
1098: String url = null;
1099:
1100:
1101:
1102:
1103:
1104: ContourEntity entity = new ContourEntity(
1105: (RectangularShape) entityArea.clone(), tip, url
1106: );
1107: entity.setIndex(k);
1108: entities.add(entity);
1109: }
1110:
1111:
1112: if (plot.isDomainCrosshairLockedOnData()) {
1113: if (plot.isRangeCrosshairLockedOnData()) {
1114:
1115: crosshairState.updateCrosshairPoint(
1116: x[k], y[k], transX, transY, PlotOrientation.VERTICAL
1117: );
1118: }
1119: else {
1120:
1121: crosshairState.updateCrosshairX(transX);
1122: }
1123: }
1124: else {
1125: if (plot.isRangeCrosshairLockedOnData()) {
1126:
1127: crosshairState.updateCrosshairY(transY);
1128: }
1129: }
1130: }
1131:
1132:
1133: g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, antiAlias);
1134:
1135: return;
1136:
1137: }
1138:
1139:
1148: protected void drawVerticalLine(Graphics2D g2, Rectangle2D dataArea,
1149: double value, Stroke stroke, Paint paint) {
1150:
1151: double xx = getDomainAxis().valueToJava2D(
1152: value, dataArea, RectangleEdge.BOTTOM
1153: );
1154: Line2D line = new Line2D.Double(
1155: xx, dataArea.getMinY(), xx, dataArea.getMaxY()
1156: );
1157: g2.setStroke(stroke);
1158: g2.setPaint(paint);
1159: g2.draw(line);
1160:
1161: }
1162:
1163:
1172: protected void drawHorizontalLine(Graphics2D g2, Rectangle2D dataArea,
1173: double value, Stroke stroke,
1174: Paint paint) {
1175:
1176: double yy = getRangeAxis().valueToJava2D(
1177: value, dataArea, RectangleEdge.LEFT
1178: );
1179: Line2D line = new Line2D.Double(
1180: dataArea.getMinX(), yy, dataArea.getMaxX(), yy
1181: );
1182: g2.setStroke(stroke);
1183: g2.setPaint(paint);
1184: g2.draw(line);
1185:
1186: }
1187:
1188:
1195: public void handleClick(int x, int y, PlotRenderingInfo info) {
1196:
1197:
1218: }
1219:
1220:
1225: public void zoom(double percent) {
1226:
1227: if (percent > 0) {
1228:
1229:
1230:
1231:
1232:
1233:
1234:
1235: }
1236: else {
1237: getRangeAxis().setAutoRange(true);
1238: getDomainAxis().setAutoRange(true);
1239: }
1240:
1241: }
1242:
1243:
1248: public String getPlotType() {
1249: return localizationResources.getString("Contour_Plot");
1250: }
1251:
1252:
1259: public Range getDataRange(ValueAxis axis) {
1260:
1261: if (this.dataset == null) {
1262: return null;
1263: }
1264:
1265: Range result = null;
1266:
1267: if (axis == getDomainAxis()) {
1268: result = DatasetUtilities.findDomainBounds(this.dataset);
1269: }
1270: else if (axis == getRangeAxis()) {
1271: result = DatasetUtilities.findRangeBounds(this.dataset);
1272: }
1273:
1274: return result;
1275:
1276: }
1277:
1278:
1283: public Range getContourDataRange() {
1284:
1285: Range result = null;
1286:
1287: ContourDataset data = getDataset();
1288:
1289: if (data != null) {
1290: Range h = getDomainAxis().getRange();
1291: Range v = getRangeAxis().getRange();
1292: result = this.visibleRange(data, h, v);
1293: }
1294:
1295: return result;
1296: }
1297:
1298:
1305: public void propertyChange(PropertyChangeEvent event) {
1306: notifyListeners(new PlotChangeEvent(this));
1307: }
1308:
1309:
1317: public void datasetChanged(DatasetChangeEvent event) {
1318: if (this.domainAxis != null) {
1319: this.domainAxis.configure();
1320: }
1321: if (this.rangeAxis != null) {
1322: this.rangeAxis.configure();
1323: }
1324: if (this.colorBar != null) {
1325: this.colorBar.configure(this);
1326: }
1327: super.datasetChanged(event);
1328: }
1329:
1330:
1335: public ColorBar getColorBar() {
1336: return this.colorBar;
1337: }
1338:
1339:
1344: public boolean isDomainCrosshairVisible() {
1345: return this.domainCrosshairVisible;
1346: }
1347:
1348:
1353: public void setDomainCrosshairVisible(boolean flag) {
1354:
1355: if (this.domainCrosshairVisible != flag) {
1356: this.domainCrosshairVisible = flag;
1357: notifyListeners(new PlotChangeEvent(this));
1358: }
1359:
1360: }
1361:
1362:
1368: public boolean isDomainCrosshairLockedOnData() {
1369: return this.domainCrosshairLockedOnData;
1370: }
1371:
1372:
1378: public void setDomainCrosshairLockedOnData(boolean flag) {
1379: if (this.domainCrosshairLockedOnData != flag) {
1380: this.domainCrosshairLockedOnData = flag;
1381: notifyListeners(new PlotChangeEvent(this));
1382: }
1383: }
1384:
1385:
1390: public double getDomainCrosshairValue() {
1391: return this.domainCrosshairValue;
1392: }
1393:
1394:
1402: public void setDomainCrosshairValue(double value) {
1403:
1404: setDomainCrosshairValue(value, true);
1405:
1406: }
1407:
1408:
1418: public void setDomainCrosshairValue(double value, boolean notify) {
1419:
1420: this.domainCrosshairValue = value;
1421: if (isDomainCrosshairVisible() && notify) {
1422: notifyListeners(new PlotChangeEvent(this));
1423: }
1424:
1425: }
1426:
1427:
1432: public Stroke getDomainCrosshairStroke() {
1433: return this.domainCrosshairStroke;
1434: }
1435:
1436:
1442: public void setDomainCrosshairStroke(Stroke stroke) {
1443: this.domainCrosshairStroke = stroke;
1444: notifyListeners(new PlotChangeEvent(this));
1445: }
1446:
1447:
1452: public Paint getDomainCrosshairPaint() {
1453: return this.domainCrosshairPaint;
1454: }
1455:
1456:
1462: public void setDomainCrosshairPaint(Paint paint) {
1463: this.domainCrosshairPaint = paint;
1464: notifyListeners(new PlotChangeEvent(this));
1465: }
1466:
1467:
1472: public boolean isRangeCrosshairVisible() {
1473: return this.rangeCrosshairVisible;
1474: }
1475:
1476:
1481: public void setRangeCrosshairVisible(boolean flag) {
1482:
1483: if (this.rangeCrosshairVisible != flag) {
1484: this.rangeCrosshairVisible = flag;
1485: notifyListeners(new PlotChangeEvent(this));
1486: }
1487:
1488: }
1489:
1490:
1496: public boolean isRangeCrosshairLockedOnData() {
1497: return this.rangeCrosshairLockedOnData;
1498: }
1499:
1500:
1506: public void setRangeCrosshairLockedOnData(boolean flag) {
1507:
1508: if (this.rangeCrosshairLockedOnData != flag) {
1509: this.rangeCrosshairLockedOnData = flag;
1510: notifyListeners(new PlotChangeEvent(this));
1511: }
1512:
1513: }
1514:
1515:
1520: public double getRangeCrosshairValue() {
1521: return this.rangeCrosshairValue;
1522: }
1523:
1524:
1532: public void setRangeCrosshairValue(double value) {
1533:
1534: setRangeCrosshairValue(value, true);
1535:
1536: }
1537:
1538:
1548: public void setRangeCrosshairValue(double value, boolean notify) {
1549:
1550: this.rangeCrosshairValue = value;
1551: if (isRangeCrosshairVisible() && notify) {
1552: notifyListeners(new PlotChangeEvent(this));
1553: }
1554:
1555: }
1556:
1557:
1562: public Stroke getRangeCrosshairStroke() {
1563: return this.rangeCrosshairStroke;
1564: }
1565:
1566:
1572: public void setRangeCrosshairStroke(Stroke stroke) {
1573: this.rangeCrosshairStroke = stroke;
1574: notifyListeners(new PlotChangeEvent(this));
1575: }
1576:
1577:
1582: public Paint getRangeCrosshairPaint() {
1583: return this.rangeCrosshairPaint;
1584: }
1585:
1586:
1592: public void setRangeCrosshairPaint(Paint paint) {
1593: this.rangeCrosshairPaint = paint;
1594: notifyListeners(new PlotChangeEvent(this));
1595: }
1596:
1597:
1602: public ContourToolTipGenerator getToolTipGenerator() {
1603: return this.toolTipGenerator;
1604: }
1605:
1606:
1611: public void setToolTipGenerator(ContourToolTipGenerator generator) {
1612:
1613:
1614: this.toolTipGenerator = generator;
1615:
1616: }
1617:
1618:
1623: public XYURLGenerator getURLGenerator() {
1624: return this.urlGenerator;
1625: }
1626:
1627:
1632: public void setURLGenerator(XYURLGenerator urlGenerator) {
1633:
1634:
1635: this.urlGenerator = urlGenerator;
1636:
1637: }
1638:
1639:
1648: public void drawDomainMarker(Graphics2D g2,
1649: ContourPlot plot,
1650: ValueAxis domainAxis,
1651: Marker marker,
1652: Rectangle2D dataArea) {
1653:
1654: if (marker instanceof ValueMarker) {
1655: ValueMarker vm = (ValueMarker) marker;
1656: double value = vm.getValue();
1657: Range range = domainAxis.getRange();
1658: if (!range.contains(value)) {
1659: return;
1660: }
1661:
1662: double x = domainAxis.valueToJava2D(
1663: value, dataArea, RectangleEdge.BOTTOM
1664: );
1665: Line2D line = new Line2D.Double(
1666: x, dataArea.getMinY(), x, dataArea.getMaxY()
1667: );
1668: Paint paint = marker.getOutlinePaint();
1669: Stroke stroke = marker.getOutlineStroke();
1670: g2.setPaint(paint != null ? paint : Plot.DEFAULT_OUTLINE_PAINT);
1671: g2.setStroke(stroke != null ? stroke : Plot.DEFAULT_OUTLINE_STROKE);
1672: g2.draw(line);
1673: }
1674:
1675: }
1676:
1677:
1686: public void drawRangeMarker(Graphics2D g2,
1687: ContourPlot plot,
1688: ValueAxis rangeAxis,
1689: Marker marker,
1690: Rectangle2D dataArea) {
1691:
1692: if (marker instanceof ValueMarker) {
1693: ValueMarker vm = (ValueMarker) marker;
1694: double value = vm.getValue();
1695: Range range = rangeAxis.getRange();
1696: if (!range.contains(value)) {
1697: return;
1698: }
1699:
1700: double y = rangeAxis.valueToJava2D(
1701: value, dataArea, RectangleEdge.LEFT
1702: );
1703: Line2D line = new Line2D.Double(
1704: dataArea.getMinX(), y, dataArea.getMaxX(), y
1705: );
1706: Paint paint = marker.getOutlinePaint();
1707: Stroke stroke = marker.getOutlineStroke();
1708: g2.setPaint(paint != null ? paint : Plot.DEFAULT_OUTLINE_PAINT);
1709: g2.setStroke(stroke != null ? stroke : Plot.DEFAULT_OUTLINE_STROKE);
1710: g2.draw(line);
1711: }
1712:
1713: }
1714:
1715:
1719: public ClipPath getClipPath() {
1720: return this.clipPath;
1721: }
1722:
1723:
1727: public void setClipPath(ClipPath clipPath) {
1728: this.clipPath = clipPath;
1729: }
1730:
1731:
1735: public double getPtSizePct() {
1736: return this.ptSizePct;
1737: }
1738:
1739:
1743: public boolean isRenderAsPoints() {
1744: return this.renderAsPoints;
1745: }
1746:
1747:
1751: public void setPtSizePct(double ptSizePct) {
1752: this.ptSizePct = ptSizePct;
1753: }
1754:
1755:
1759: public void setRenderAsPoints(boolean renderAsPoints) {
1760: this.renderAsPoints = renderAsPoints;
1761: }
1762:
1763:
1768: public void axisChanged(AxisChangeEvent event) {
1769: Object source = event.getSource();
1770: if (source.equals(this.rangeAxis) || source.equals(this.domainAxis)) {
1771: ColorBar cba = this.colorBar;
1772: if (this.colorBar.getAxis().isAutoRange()) {
1773: cba.getAxis().configure();
1774: }
1775:
1776: }
1777: super.axisChanged(event);
1778: }
1779:
1780:
1789: public Range visibleRange(ContourDataset data, Range x, Range y) {
1790: Range range = null;
1791: range = data.getZValueRange(x, y);
1792: return range;
1793: }
1794:
1795:
1799: public Paint getMissingPaint() {
1800: return this.missingPaint;
1801: }
1802:
1803:
1808: public void setMissingPaint(Paint paint) {
1809: this.missingPaint = paint;
1810: }
1811:
1812:
1820: public void zoomDomainAxes(double x, double y, double factor) {
1821:
1822: }
1823:
1824:
1832: public void zoomDomainAxes(double x, double y, double lowerPercent,
1833: double upperPercent) {
1834:
1835: }
1836:
1837:
1844: public void zoomRangeAxes(double x, double y, double factor) {
1845:
1846: }
1847:
1848:
1856: public void zoomRangeAxes(double x, double y, double lowerPercent,
1857: double upperPercent) {
1858:
1859: }
1860:
1861:
1866: public boolean isDomainZoomable() {
1867: return false;
1868: }
1869:
1870:
1875: public boolean isRangeZoomable() {
1876: return false;
1877: }
1878:
1879:
1883: public Object clone() throws CloneNotSupportedException {
1884: ContourPlot clone = (ContourPlot) super.clone();
1885:
1886: if (this.domainAxis != null) {
1887: clone.domainAxis = (ValueAxis) this.domainAxis.clone();
1888: clone.domainAxis.setPlot(clone);
1889: clone.domainAxis.addChangeListener(clone);
1890: }
1891: if (this.rangeAxis != null) {
1892: clone.rangeAxis = (ValueAxis) this.rangeAxis.clone();
1893: clone.rangeAxis.setPlot(clone);
1894: clone.rangeAxis.addChangeListener(clone);
1895: }
1896:
1897: if (clone.dataset != null) {
1898: clone.dataset.addChangeListener(clone);
1899: }
1900:
1901: if (this.colorBar != null) {
1902: clone.colorBar = (ColorBar) this.colorBar.clone();
1903: }
1904:
1905: clone.domainMarkers = (List) ObjectUtilities.deepClone(
1906: this.domainMarkers
1907: );
1908: clone.rangeMarkers = (List) ObjectUtilities.deepClone(
1909: this.rangeMarkers
1910: );
1911: clone.annotations = (List) ObjectUtilities.deepClone(this.annotations);
1912:
1913: if (this.clipPath != null) {
1914: clone.clipPath = (ClipPath) this.clipPath.clone();
1915: }
1916:
1917: return clone;
1918: }
1919:
1920: }