changeset 1817:595c404523a6

Rewritten CrossSectionApp to be useful as test bed for 'Raum/Flaeche' operations. flys-artifacts/trunk@3146 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Thu, 03 Nov 2011 09:47:52 +0000 (2011-11-03)
parents 5364b86a0880
children e3eb1ea885a7
files flys-artifacts/ChangeLog flys-artifacts/src/main/java/de/intevation/flys/artifacts/charts/CrossSectionApp.java flys-artifacts/src/main/java/de/intevation/flys/utils/Pair.java
diffstat 3 files changed, 358 insertions(+), 143 deletions(-) [+]
line wrap: on
line diff
--- a/flys-artifacts/ChangeLog	Wed Nov 02 15:02:23 2011 +0000
+++ b/flys-artifacts/ChangeLog	Thu Nov 03 09:47:52 2011 +0000
@@ -1,3 +1,10 @@
+2011-11-03  Sascha L. Teichmann <sascha.teichmann@intevation.de>
+	
+	* src/main/java/de/intevation/flys/utils/Pair.java: New. A generic pair.
+
+	* src/main/java/de/intevation/flys/artifacts/charts/CrossSectionApp.java:
+	  Rewritten to useful as test bed for "Raum/Flaeche" operations.
+
 2011-11-02  Ingo Weinzierl <ingo@intevation.de>
 
 	* src/main/java/de/intevation/flys/artifacts/model/LayerInfo.java: Added
--- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/charts/CrossSectionApp.java	Wed Nov 02 15:02:23 2011 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/charts/CrossSectionApp.java	Thu Nov 03 09:47:52 2011 +0000
@@ -1,58 +1,72 @@
 package de.intevation.flys.artifacts.charts;
 
-import java.math.MathContext;
-
-import java.awt.Dimension;
-import java.awt.BorderLayout;
-import java.awt.FlowLayout;
-
-import javax.swing.JPanel;
-import javax.swing.JButton;
-import javax.swing.JComboBox;
-import javax.swing.JTextField;
-import javax.swing.DefaultComboBoxModel;
-
-import java.awt.event.ItemListener;
-import java.awt.event.ItemEvent;
-import java.awt.event.ActionListener;
-import java.awt.event.ActionEvent;
-
-import java.awt.geom.Point2D;
-
-import java.util.List;
+import de.intevation.flys.backend.SessionFactoryProvider;
 
-import java.io.File;
-import java.io.IOException;
-import java.io.FileWriter;
-import java.io.PrintWriter;
-
-import org.jfree.ui.ApplicationFrame;
-import org.jfree.ui.RefineryUtilities;
-
-import org.jfree.chart.ChartFactory;
-
-import org.jfree.chart.plot.PlotOrientation;
-import org.jfree.chart.plot.XYPlot;
-
-import org.jfree.chart.ChartUtilities;
-import org.jfree.chart.JFreeChart;
-import org.jfree.chart.ChartPanel;
-
-import org.jfree.chart.axis.NumberAxis;
-
-import org.jfree.data.xy.XYDataset;
-import org.jfree.data.xy.DefaultXYDataset;
+import de.intevation.flys.geom.Lines;
 
 import de.intevation.flys.model.CrossSection;
 import de.intevation.flys.model.CrossSectionLine;
 import de.intevation.flys.model.CrossSectionPoint;
 
-import de.intevation.flys.geom.Lines;
+import de.intevation.flys.utils.Pair;
 
-import de.intevation.flys.backend.SessionFactoryProvider;
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+import java.awt.FlowLayout;
 
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
+
+import java.awt.geom.Point2D;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+import java.math.MathContext;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+import javax.swing.DefaultComboBoxModel;
+import javax.swing.JButton;
+import javax.swing.JComboBox;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTable;
+import javax.swing.JTextField;
+
+import javax.swing.event.TableModelEvent;
+import javax.swing.event.TableModelListener;
+
+import javax.swing.table.AbstractTableModel;
+
+import org.hibernate.Query;
 import org.hibernate.Session;
-import org.hibernate.Query;
+
+import org.jfree.chart.ChartFactory;
+import org.jfree.chart.ChartPanel;
+import org.jfree.chart.ChartUtilities;
+import org.jfree.chart.JFreeChart;
+
+import org.jfree.chart.axis.NumberAxis;
+
+import org.jfree.chart.plot.PlotOrientation;
+import org.jfree.chart.plot.XYPlot;
+
+import org.jfree.data.xy.DefaultXYDataset;
+import org.jfree.data.xy.XYDataset;
+import org.jfree.data.xy.XYSeries;
+import org.jfree.data.xy.XYSeriesCollection;
+
+import org.jfree.ui.ApplicationFrame;
+import org.jfree.ui.RefineryUtilities;
 
 public class CrossSectionApp
 extends      ApplicationFrame
@@ -63,7 +77,6 @@
 
     protected Session session;
 
-    protected JComboBox crossSectionsCB;
     protected JComboBox crossSectionLinesCB;
     protected JTextField waterlevelTF;
 
@@ -71,31 +84,116 @@
 
     protected Double lastWaterLevel;
 
-
-    public static class CrossSectionItem {
+    protected List<CrossSection> crossSections;
+    protected boolean [] drawCrossSection;
+    protected boolean [] drawWaterLevel;
+    protected boolean [] drawGround;
 
-        CrossSection crossSection;
+    protected Map<Double, List<Pair<CrossSection, CrossSectionLine>>> km2lines;
 
-        public CrossSectionItem(CrossSection crossSection) {
-            this.crossSection = crossSection;
+    public class CrossSectionTableModel extends AbstractTableModel {
+
+        @Override
+        public String getColumnName(int col) {
+            switch (col) {
+                case 0: return "Peilungsname";
+                case 1: return "Peilung";
+                case 2: return "Wasserstand";
+                case 3: return "Boden";
+            }
+            return "";
+        }
+
+        @Override
+        public int getColumnCount() {
+            return 4; 
+        }
+
+        @Override
+        public int getRowCount() {
+            return crossSections != null ? crossSections.size() : 0;
+        }
+
+        @Override
+        public Object getValueAt(int row, int col) {
+            if (crossSections == null) return null;
+            switch (col) {
+                case 0: return crossSections.get(row).getDescription();
+                case 1: return drawCrossSection[row];
+                case 2: return drawWaterLevel[row];
+                case 3: return drawGround[row];
+            }
+            return null;
+        }
+
+        @Override
+        public void setValueAt(Object value, int row, int col) {
+            switch (col) {
+                case 1: 
+                    if (change(drawCrossSection, row, (Boolean)value)) {
+                        fireTableCellUpdated(row, col);
+                    }
+                    break;
+                case 2:
+                    if (change(drawWaterLevel, row, (Boolean)value)) {
+                        fireTableCellUpdated(row, col);
+                    }
+                    break;
+                case 3:
+                    if (change(drawGround, row, (Boolean)value)) {
+                        fireTableCellUpdated(row, col);
+                    }
+                    break;
+            }
+        }
+
+        @Override
+        public Class<?> getColumnClass(int columnIndex) {
+            switch (columnIndex) {
+                case 0: return String.class;
+                case 1: return Boolean.class;
+                case 2: return Boolean.class;
+                case 3: return Boolean.class;
+            }
+            return null;
+        }
+
+        @Override
+        public boolean isCellEditable(
+            int rowIndex,
+            int columnIndex
+        ) {
+            return columnIndex >= 1 && columnIndex <= 3;
+        }
+    } // class CrossSectionTableModel
+
+    private static boolean change(
+        boolean [] values,
+        int        index, 
+        boolean    value
+    ) {
+        if (values[index] != value) {
+            values[index] = value;
+            return true;
+        }
+        return false;
+    }
+
+    public static class CrossSectionLineItem {
+
+        Double km;
+        List<Pair<CrossSection, CrossSectionLine>> lines;
+
+        public CrossSectionLineItem(
+            Double km, 
+            List<Pair<CrossSection, CrossSectionLine>> lines
+        ) {
+            this.km    = km;
+            this.lines = lines;
         }
 
         public String toString() {
-            return crossSection.getDescription();
-        }
-    } // CrossSectionItem
-
-    public static class CrossSectionLineItem {
-
-        CrossSectionLine line;
-
-        public CrossSectionLineItem(CrossSectionLine line) {
-            this.line = line;
-        }
-
-        public String toString() {
-            double v = line.getKm().doubleValue();
-            return String.valueOf(Math.round(v * 1000.0)/1000d);
+            return String.valueOf(km);
         }
     } // CrossSectionLineItem
 
@@ -107,7 +205,7 @@
             .openSession();
 
         JPanel content = createContent();
-        content.setPreferredSize(new Dimension(640, 480));
+        content.setPreferredSize(new Dimension(800, 480));
         setContentPane(content);
 
     }
@@ -119,45 +217,50 @@
         return query.list();
     }
 
+    protected Map<Double, List<Pair<CrossSection, CrossSectionLine>>> loadAllLines(
+        List<CrossSection> crossSections
+    ) {
+        Map<Double, List<Pair<CrossSection, CrossSectionLine>>> km2lines =
+            new TreeMap<Double, List<Pair<CrossSection, CrossSectionLine>>>();
+        for (CrossSection cs: crossSections) {
+            List<CrossSectionLine> lines = cs.getLines();
+            for (CrossSectionLine csl: lines) {
+                Double km = Math.round(csl.getKm().doubleValue() * 1000d)/1000d;
+                List<Pair<CrossSection, CrossSectionLine>> ls = km2lines.get(km);
+                if (ls == null) {
+                    ls = new ArrayList<Pair<CrossSection, CrossSectionLine>>(2);
+                    km2lines.put(km, ls);
+                }
+                ls.add(new Pair<CrossSection, CrossSectionLine>(cs, csl));
+            }
+        }
+        return km2lines;
+    }
+
     public JPanel createContent() {
         JPanel panel = new JPanel(new BorderLayout());
 
 
         JPanel nav = new JPanel(new FlowLayout());
 
-        Object [] csis = createCrossSectionItems();
-        crossSectionsCB = new JComboBox(csis);
-
-        DefaultComboBoxModel dcbm;
+        crossSections = crossSections(RIVER);
+        km2lines = loadAllLines(crossSections);
+        drawCrossSection = new boolean[crossSections.size()];
+        Arrays.fill(drawCrossSection, true);
 
-        if (csis.length > 0) {
-            Object [] cslis =
-                createCrossSectionLineItems(
-                    ((CrossSectionItem)csis[0]).crossSection);
-            dcbm = new DefaultComboBoxModel(cslis);
-            if (cslis.length > 0) {
-                dcbm.setSelectedItem(cslis[0]);
-            }
-        }
-        else {
-            dcbm = new DefaultComboBoxModel(new Object[0]);
-        }
+        drawWaterLevel = new boolean[crossSections.size()];
+        drawGround     = new boolean[crossSections.size()];
+
+        Object [] clis = createCrossSectionLineItems(km2lines);
+
+        DefaultComboBoxModel dcbm = new DefaultComboBoxModel(clis);
 
         crossSectionLinesCB = new JComboBox(dcbm);
 
-        nav.add(crossSectionsCB);
         nav.add(crossSectionLinesCB);
 
-        crossSectionsCB.addItemListener(new ItemListener() {
-            public void itemStateChanged(ItemEvent ie) {
-                if (ie.getStateChange() == ItemEvent.SELECTED) {
-                    updateCrossSection(
-                        ((CrossSectionItem)ie.getItem()).crossSection);
-                }
-            }
-        });
-
         crossSectionLinesCB.addItemListener(new ItemListener() {
+            @Override
             public void itemStateChanged(ItemEvent ie) {
                 if (ie.getStateChange() == ItemEvent.SELECTED) {
                     updateChart();
@@ -165,10 +268,10 @@
             }
         });
 
-
         waterlevelTF = new JTextField(5);
 
         waterlevelTF.addActionListener(new ActionListener() {
+            @Override
             public void actionPerformed(ActionEvent ae) {
                 waterLevelChanged();
             }
@@ -179,6 +282,7 @@
         JButton dump = new JButton("dump");
 
         dump.addActionListener(new ActionListener() {
+            @Override
             public void actionPerformed(ActionEvent ae) {
                 dumpData();
             }
@@ -186,12 +290,31 @@
 
         nav.add(dump);
 
-        panel.add(nav, BorderLayout.SOUTH);
 
         chartPanel = createChartPanel();
 
         panel.add(chartPanel, BorderLayout.CENTER);
 
+
+        CrossSectionTableModel cstm = new CrossSectionTableModel();
+
+        cstm.addTableModelListener(new TableModelListener() {
+            @Override
+            public void tableChanged(TableModelEvent e) {
+                updateChart();
+            }
+        });
+
+        JTable crossTable = new JTable(cstm);
+
+        JPanel west = new JPanel(new BorderLayout());
+        JScrollPane scrollPane = new JScrollPane(crossTable);
+        west.add(scrollPane);
+
+        west.add(nav, BorderLayout.SOUTH);
+
+        panel.add(west, BorderLayout.WEST);
+
         return panel;
     }
 
@@ -214,8 +337,8 @@
             (CrossSectionLineItem)crossSectionLinesCB.getSelectedItem();
 
         JFreeChart chart = createChart(csli == null
-            ? new DefaultXYDataset()
-            : generateDataset(csli.line, lastWaterLevel));
+            ? new XYSeriesCollection()
+            : generateDataset());
 
         chartPanel.setChart(chart);
     }
@@ -225,13 +348,16 @@
             (CrossSectionLineItem)crossSectionLinesCB.getSelectedItem();
 
         JFreeChart chart = createChart(csli == null
-            ? new DefaultXYDataset()
-            : generateDataset(csli.line, lastWaterLevel));
+            ? new XYSeriesCollection()
+            : generateDataset());
 
         return new ChartPanel(chart);
     }
 
     protected void dumpData() {
+    }
+    /*
+    protected void dumpData() {
 
         CrossSectionLineItem csli =
             (CrossSectionLineItem)crossSectionLinesCB.getSelectedItem();
@@ -282,75 +408,117 @@
             }
         }
     }
+    */
 
-    public static XYDataset generateDataset(
-        CrossSectionLine line,
-        Double           waterlevel
+    public void generateWaterLevels(
+        List<Point2D>      points,
+        XYSeriesCollection collection
     ) {
-        DefaultXYDataset dataset = new DefaultXYDataset();
-
-        List<Point2D> points = line.fetchCrossSectionLinesPoints();
-
-        if (points.isEmpty()) {
-            return dataset;
+        if (points == null || points.isEmpty()) {
+            return;
         }
 
-        if (waterlevel != null) {
-            double [][] data = Lines.createWaterLines(points, waterlevel);
-            dataset.addSeries(String.valueOf(waterlevel), data);
+        if (lastWaterLevel != null) {
+            double [][] data = Lines.createWaterLines(points, lastWaterLevel);
+            XYSeries series =
+                new XYSeries(String.valueOf(lastWaterLevel), false);
+
+            double [] x = data[0];
+            double [] y = data[1];
+            for (int i = 0; i < x.length; ++i) {
+                series.add(x[i], y[i], false);
+            }
+
+            collection.addSeries(series);
         }
+    }
 
-        CrossSection cs = line.getCrossSection();
-
-        String legend = (cs != null ? cs.getDescription() : "???")
-            + " " + Math.round(line.getKm().doubleValue() * 1000d)/1000d;
+    public void generateProfile(
+        List<Point2D>      points,
+        String             legend,
+        XYSeriesCollection collection
+    ) {
+        if (points == null || points.isEmpty()) {
+            return;
+        }
 
         double [][] values = CrossSectionLine.fetchCrossSectionProfile(points);
 
-        dataset.addSeries(legend, values);
+        XYSeries series = new XYSeries(legend, false);
 
-        return dataset;
+        double [] x = values[0];
+        double [] y = values[1];
+        for (int i = 0; i < x.length; ++i) {
+            series.add(x[i], y[i], false);
+        }
+
+        collection.addSeries(series);
     }
 
-    protected void updateCrossSection(CrossSection crossSection) {
-        Object [] cslis = createCrossSectionLineItems(crossSection);
-        DefaultComboBoxModel dcbm = new DefaultComboBoxModel(cslis);
-        if (cslis.length > 0) {
-            dcbm.setSelectedItem(cslis[0]);
+    public XYSeriesCollection generateDataset() {
+        XYSeriesCollection collection = new XYSeriesCollection();
+
+        CrossSectionLineItem csli =
+            (CrossSectionLineItem)crossSectionLinesCB.getSelectedItem();
+
+        for (int i = 0; i < drawCrossSection.length; ++i) {
+            List<Point2D> points = null;
+
+            if (drawCrossSection[i]) {
+                CrossSection cs = crossSections.get(i);
+                for (Pair<CrossSection, CrossSectionLine> csl: csli.lines) {
+                    if (csl.getA() == cs) {
+                        points = csl.getB().fetchCrossSectionLinesPoints();
+                        generateProfile(
+                            points,
+                            cs.getDescription(),
+                            collection);
+                        break;
+                    }
+                }
+            }
+
+            if (drawWaterLevel[i]) {
+                CrossSection cs = crossSections.get(i);
+                for (Pair<CrossSection, CrossSectionLine> csl: csli.lines) {
+                    if (csl.getA() == cs) {
+                        if (points != null) {
+                            points = csl.getB().fetchCrossSectionLinesPoints();
+                        }
+                        generateWaterLevels(
+                            points,
+                            collection);
+                        break;
+                    }
+                }
+            }
+
         }
-        crossSectionLinesCB.setModel(dcbm);
-        if (cslis.length > 0) {
-            CrossSectionLine line =
-                ((CrossSectionLineItem)cslis[0]).line;
-        }
-        updateChart();
+
+        return collection;
     }
 
-    protected Object [] createCrossSectionLineItems(CrossSection cs) {
-        List<CrossSectionLine> lines = cs.getLines();
-        Object [] result = new Object[lines.size()];
-        for (int i = 0; i < result.length; ++i) {
-            result[i] = new CrossSectionLineItem(lines.get(i));
+    protected Object [] createCrossSectionLineItems(
+        Map<Double, List<Pair<CrossSection, CrossSectionLine>>> km2lines
+    ) {
+        Object [] result = new Object[km2lines.size()];
+        int i = 0;
+        for (Map.Entry<Double, List<Pair<CrossSection, CrossSectionLine>>> entry:
+            km2lines.entrySet()) {
+            result[i++] = new CrossSectionLineItem(
+                entry.getKey(),
+                entry.getValue());
         }
         return result;
     }
 
 
-    protected Object [] createCrossSectionItems() {
-        List<CrossSection> crossSections = crossSections(RIVER);
-        Object [] result = new Object[crossSections.size()];
-        for (int i = 0; i < result.length; ++i) {
-            result[i] = new CrossSectionItem(crossSections.get(i));
-        }
-        return result;
-    }
-
-    public static JFreeChart createChart(XYDataset dataset) {
+    public static JFreeChart createChart(XYSeriesCollection collection) {
         JFreeChart chart = ChartFactory.createXYLineChart(
             null,
             "Abstand [m]",
             "H\u00f6he [m]",
-            dataset,
+            collection,
             PlotOrientation.VERTICAL,
             true,
             true,
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/utils/Pair.java	Thu Nov 03 09:47:52 2011 +0000
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2010 by Intevation GmbH
+ *
+ * This program is free software under the LGPL (>=v2.1)
+ * Read the file LGPL.txt coming with the software for details
+ * or visit http://www.gnu.org/licenses/ if it does not exist.
+ */
+
+package de.intevation.flys.utils;
+
+import java.io.Serializable;
+
+/**
+ * @param <A>
+ * @param <B>
+ * @author <a href="mailto:sascha.teichmann@intevation.de">Sascha L. Teichmann</a>
+ */
+public final class Pair<A, B>
+implements         Serializable
+{
+    private A a;
+    private B b;
+
+    private Pair() {
+    }
+
+    public Pair(A a, B b) {
+        this.a = a;
+        this.b = b;
+    }
+
+    public A getA() {
+        return a;
+    }
+
+    public B getB() {
+        return b;
+    }
+}
+// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org