# HG changeset patch # User Sascha L. Teichmann # Date 1320313672 0 # Node ID 595c404523a69c62d7a5672aa622b0c3aa821e69 # Parent 5364b86a08806cf416e4fc8a9b8819203daa7551 Rewritten CrossSectionApp to be useful as test bed for 'Raum/Flaeche' operations. flys-artifacts/trunk@3146 c6561f87-3c4e-4783-a992-168aeb5c3f6f diff -r 5364b86a0880 -r 595c404523a6 flys-artifacts/ChangeLog --- 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 + + * 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 * src/main/java/de/intevation/flys/artifacts/model/LayerInfo.java: Added diff -r 5364b86a0880 -r 595c404523a6 flys-artifacts/src/main/java/de/intevation/flys/artifacts/charts/CrossSectionApp.java --- 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 crossSections; + protected boolean [] drawCrossSection; + protected boolean [] drawWaterLevel; + protected boolean [] drawGround; - CrossSection crossSection; + protected Map>> 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> lines; + + public CrossSectionLineItem( + Double km, + List> 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>> loadAllLines( + List crossSections + ) { + Map>> km2lines = + new TreeMap>>(); + for (CrossSection cs: crossSections) { + List lines = cs.getLines(); + for (CrossSectionLine csl: lines) { + Double km = Math.round(csl.getKm().doubleValue() * 1000d)/1000d; + List> ls = km2lines.get(km); + if (ls == null) { + ls = new ArrayList>(2); + km2lines.put(km, ls); + } + ls.add(new Pair(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 points, + XYSeriesCollection collection ) { - DefaultXYDataset dataset = new DefaultXYDataset(); - - List 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 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 points = null; + + if (drawCrossSection[i]) { + CrossSection cs = crossSections.get(i); + for (Pair 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 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 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>> km2lines + ) { + Object [] result = new Object[km2lines.size()]; + int i = 0; + for (Map.Entry>> entry: + km2lines.entrySet()) { + result[i++] = new CrossSectionLineItem( + entry.getKey(), + entry.getValue()); } return result; } - protected Object [] createCrossSectionItems() { - List 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, diff -r 5364b86a0880 -r 595c404523a6 flys-artifacts/src/main/java/de/intevation/flys/utils/Pair.java --- /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 + * @param + * @author Sascha L. Teichmann + */ +public final class Pair +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 :