changeset 1883:eb671699fbc2

CrossSectionApp: Draw water, too. flys-artifacts/trunk@3242 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Sat, 12 Nov 2011 22:26:27 +0000
parents d67a9ca116c3
children 4ae9c92feb8c
files flys-artifacts/ChangeLog flys-artifacts/src/main/java/de/intevation/flys/artifacts/charts/CrossSectionApp.java flys-artifacts/src/main/java/de/intevation/flys/jfree/StableXYDifferenceRenderer.java
diffstat 3 files changed, 146 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/flys-artifacts/ChangeLog	Sat Nov 12 12:07:39 2011 +0000
+++ b/flys-artifacts/ChangeLog	Sat Nov 12 22:26:27 2011 +0000
@@ -1,3 +1,11 @@
+2011-11-12	Sascha L. Teichmann	<sascha.teichmann@intevation.de>
+
+	* src/main/java/de/intevation/flys/artifacts/charts/CrossSectionApp.java:
+	  Draw water, too.
+
+	* src/main/java/de/intevation/flys/jfree/StableXYDifferenceRenderer.java:
+	  First code to split datasets by NaNs. WIP.
+
 2011-11-12	Sascha L. Teichmann	<sascha.teichmann@intevation.de>
 
 	* src/main/java/de/intevation/flys/artifacts/charts/CrossSectionApp.java:
--- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/charts/CrossSectionApp.java	Sat Nov 12 12:07:39 2011 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/charts/CrossSectionApp.java	Sat Nov 12 22:26:27 2011 +0000
@@ -22,6 +22,7 @@
 import java.awt.event.ItemListener;
 
 import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
 
 import java.io.File;
 import java.io.FileWriter;
@@ -36,6 +37,12 @@
 import java.util.Map;
 import java.util.TreeMap;
 
+import java.awt.Color;
+import java.awt.Paint;
+import java.awt.TexturePaint;
+
+import java.awt.image.BufferedImage;
+
 import javax.swing.DefaultComboBoxModel;
 import javax.swing.JButton;
 import javax.swing.JComboBox;
@@ -91,9 +98,12 @@
     protected boolean [] drawCrossSection;
     protected boolean [] drawWaterLevel;
     protected boolean [] drawGround;
+    protected boolean [] drawFill;
 
     protected Map<Double, List<Pair<CrossSection, CrossSectionLine>>> km2lines;
 
+    protected static final Paint TRANSPARENT = createTransparentPaint();
+
     public class CrossSectionTableModel extends AbstractTableModel {
 
         @Override
@@ -103,13 +113,14 @@
                 case 1: return "Peilung";
                 case 2: return "Wasserstand";
                 case 3: return "Boden";
+                case 4: return "Wasser";
             }
             return "";
         }
 
         @Override
         public int getColumnCount() {
-            return 4; 
+            return 5; 
         }
 
         @Override
@@ -125,6 +136,7 @@
                 case 1: return drawCrossSection[row];
                 case 2: return drawWaterLevel[row];
                 case 3: return drawGround[row];
+                case 4: return drawFill[row];
             }
             return null;
         }
@@ -147,6 +159,11 @@
                         fireTableCellUpdated(row, col);
                     }
                     break;
+                case 4:
+                    if (change(drawFill, row, (Boolean)value)) {
+                        fireTableCellUpdated(row, col);
+                    }
+                    break;
             }
         }
 
@@ -157,6 +174,7 @@
                 case 1: return Boolean.class;
                 case 2: return Boolean.class;
                 case 3: return Boolean.class;
+                case 4: return Boolean.class;
             }
             return null;
         }
@@ -166,7 +184,7 @@
             int rowIndex,
             int columnIndex
         ) {
-            return columnIndex >= 1 && columnIndex <= 3;
+            return columnIndex >= 1 && columnIndex <= 4;
         }
     } // class CrossSectionTableModel
 
@@ -248,11 +266,12 @@
 
         crossSections = crossSections(RIVER);
         km2lines = loadAllLines(crossSections);
-        drawCrossSection = new boolean[crossSections.size()];
-        Arrays.fill(drawCrossSection, true);
 
-        drawWaterLevel = new boolean[crossSections.size()];
-        drawGround     = new boolean[crossSections.size()];
+        int CS = crossSections.size();
+        Arrays.fill(drawCrossSection = new boolean[CS], true);
+        drawWaterLevel = new boolean[CS];
+        drawGround     = new boolean[CS];
+        drawFill       = new boolean[CS];
 
         Object [] clis = createCrossSectionLineItems(km2lines);
 
@@ -427,6 +446,29 @@
             new XYSeriesCollection(series), null));
     }
 
+    public void generateFill(
+        List<Point2D>                         points,
+        String                                legend,
+        List<Pair<XYDataset, XYItemRenderer>> datasets
+    ) {
+        if (points == null || points.isEmpty() || lastWaterLevel == null) {
+            return;
+        }
+
+        double [][] data   = Lines.createWaterLines(points, lastWaterLevel);
+        double [][] values = CrossSectionLine.fetchCrossSectionProfile(points);
+
+        DefaultXYDataset dataset = new DefaultXYDataset();
+
+        dataset.addSeries(legend + "-Linie", values);
+        dataset.addSeries(legend + "-Fl\u00e4che", data);
+
+        datasets.add(new Pair<XYDataset, XYItemRenderer>(
+            dataset,
+            new StableXYDifferenceRenderer(
+                TRANSPARENT, Color.blue, false)));
+    }
+
     public void generateProfile(
         List<Point2D>                         points,
         String                                legend,
@@ -462,6 +504,9 @@
         double [][] values = CrossSectionLine.fetchCrossSectionProfile(points);
 
         DefaultXYDataset dataset = new DefaultXYDataset();
+
+        XYSeries series = new XYSeries(legend, false);
+
         dataset.addSeries(legend, values);
 
         StableXYDifferenceRenderer renderer =
@@ -483,10 +528,26 @@
             List<Point2D> points = null;
             CrossSection cs = crossSections.get(i);
 
+            if (drawFill[i]) {
+                for (Pair<CrossSection, CrossSectionLine> csl: csli.lines) {
+                    if (csl.getA() == cs) {
+                        if (points == null) {
+                            points = csl.getB().fetchCrossSectionLinesPoints();
+                        }
+
+                        generateFill(
+                            points, cs.getDescription(), datasets);
+                        break;
+                    }
+                }
+            }
+
             if (drawCrossSection[i]) {
                 for (Pair<CrossSection, CrossSectionLine> csl: csli.lines) {
                     if (csl.getA() == cs) {
-                        points = csl.getB().fetchCrossSectionLinesPoints();
+                        if (points == null) {
+                            points = csl.getB().fetchCrossSectionLinesPoints();
+                        }
 
                         generateProfile(
                             points, cs.getDescription(), datasets);
@@ -498,7 +559,7 @@
             if (drawWaterLevel[i]) {
                 for (Pair<CrossSection, CrossSectionLine> csl: csli.lines) {
                     if (csl.getA() == cs) {
-                        if (points != null) {
+                        if (points == null) {
                             points = csl.getB().fetchCrossSectionLinesPoints();
                         }
                         generateWaterLevels(points, datasets);
@@ -510,7 +571,7 @@
             if (drawGround[i]) {
                 for (Pair<CrossSection, CrossSectionLine> csl: csli.lines) {
                     if (csl.getA() == cs) {
-                        if (points != null) {
+                        if (points == null) {
                             points = csl.getB().fetchCrossSectionLinesPoints();
                         }
                         generateGround(
@@ -574,6 +635,14 @@
         return chart;
     }
 
+    protected static Paint createTransparentPaint() {
+        BufferedImage texture = new BufferedImage(
+            1, 1, BufferedImage.TYPE_4BYTE_ABGR);
+
+        return new TexturePaint(
+            texture, new Rectangle2D.Double(0d, 0d, 0d, 0d));
+    }
+
     public static void main(String [] args) {
         CrossSectionApp csa = new CrossSectionApp("Querprofile");
         csa.pack();
--- a/flys-artifacts/src/main/java/de/intevation/flys/jfree/StableXYDifferenceRenderer.java	Sat Nov 12 12:07:39 2011 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/jfree/StableXYDifferenceRenderer.java	Sat Nov 12 22:26:27 2011 +0000
@@ -86,8 +86,10 @@
 import java.io.IOException;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.LinkedList;
+import java.util.List;
 
 import org.jfree.chart.LegendItem;
 import org.jfree.chart.axis.ValueAxis;
@@ -101,6 +103,7 @@
 import org.jfree.chart.plot.XYPlot;
 import org.jfree.chart.urls.XYURLGenerator;
 import org.jfree.data.xy.XYDataset;
+import org.jfree.data.xy.DefaultXYDataset;
 import org.jfree.io.SerialUtilities;
 import org.jfree.ui.RectangleEdge;
 import org.jfree.util.PaintUtilities;
@@ -111,6 +114,8 @@
 import org.jfree.chart.renderer.xy.XYItemRenderer;
 import org.jfree.chart.renderer.xy.XYItemRendererState;
 
+import gnu.trove.TDoubleArrayList;
+
 /**
  * A renderer for an {@link XYPlot} that highlights the differences between two
  * series.  The example shown here is generated by the
@@ -359,6 +364,56 @@
         return 2;
     }
 
+    public static List<XYDataset> splitByNaNs(XYDataset dataset)  {
+        List<XYDataset> datasets = new ArrayList<XYDataset>();
+
+        switch (dataset.getSeriesCount()) {
+            case 0:
+                return datasets;
+            case 1:
+                int N = dataset.getItemCount(0);
+                TDoubleArrayList xs = new TDoubleArrayList(N);
+                TDoubleArrayList ys = new TDoubleArrayList(N);
+                for (int i = 0; i < N; ++i) {
+                    double x = dataset.getXValue(0, i);
+                    double y = dataset.getYValue(0, i);
+                    if (Double.isNaN(x) || Double.isNaN(y)) {
+                        if (!xs.isEmpty()) {
+                            DefaultXYDataset ds = new DefaultXYDataset();
+                            datasets.add(ds);
+                            ds.addSeries(
+                                dataset.getSeriesKey(0),
+                                new double [][] {
+                                    xs.toNativeArray(),
+                                    ys.toNativeArray() });
+                            xs.reset();
+                            ys.reset();
+                        }
+                    }
+                    else {
+                        xs.add(x);
+                        ys.add(y);
+                    }
+                }
+                if (!xs.isEmpty()) {
+                    DefaultXYDataset ds = new DefaultXYDataset();
+                    datasets.add(ds);
+                    ds.addSeries(
+                        dataset.getSeriesKey(0),
+                        new double [][] {
+                            xs.toNativeArray(),
+                            ys.toNativeArray() });
+                }
+                break;
+            default: // two or more
+                // TODO: split two parts
+                datasets.add(dataset);
+                break;
+        }
+
+        return datasets;
+    }
+
     /**
      * Draws the visual representation of a single data item.
      *
@@ -391,9 +446,11 @@
                          int pass) {
         switch (pass) {
             case 0:
-                drawItemPass0(g2, dataArea, info, 
-                    plot, domainAxis, rangeAxis,
-                    dataset, series, item, crosshairState);
+                for (XYDataset ds: splitByNaNs(dataset)) {
+                    drawItemPass0(g2, dataArea, info, 
+                        plot, domainAxis, rangeAxis,
+                        dataset, series, item, crosshairState);
+                }
                 break;
             case 1:
                 drawItemPass1(g2, dataArea, info,

http://dive4elements.wald.intevation.org