sascha@936: package de.intevation.flys.artifacts.charts;
sascha@936: 
sascha@936: import java.math.MathContext;
sascha@936: 
sascha@936: import java.awt.Dimension;
sascha@936: import java.awt.BorderLayout;
sascha@936: import java.awt.FlowLayout;
sascha@936: 
sascha@936: import javax.swing.JPanel;
sascha@936: import javax.swing.JButton;
sascha@936: import javax.swing.JComboBox;
sascha@938: import javax.swing.JTextField;
sascha@936: import javax.swing.DefaultComboBoxModel;
sascha@936: 
sascha@936: import java.awt.event.ItemListener;
sascha@936: import java.awt.event.ItemEvent;
sascha@936: import java.awt.event.ActionListener;
sascha@936: import java.awt.event.ActionEvent;
sascha@936: 
sascha@938: import java.awt.geom.Point2D;
sascha@938: 
sascha@936: import java.util.List;
sascha@936: 
sascha@936: import java.io.File;
sascha@936: import java.io.IOException;
sascha@936: import java.io.FileWriter;
sascha@936: import java.io.PrintWriter;
sascha@936: 
sascha@936: import org.jfree.ui.ApplicationFrame;
sascha@936: import org.jfree.ui.RefineryUtilities;
sascha@936: 
sascha@936: import org.jfree.chart.ChartFactory;
sascha@936: 
sascha@936: import org.jfree.chart.plot.PlotOrientation;
sascha@938: import org.jfree.chart.plot.XYPlot;
sascha@936: 
sascha@936: import org.jfree.chart.ChartUtilities;
sascha@936: import org.jfree.chart.JFreeChart;
sascha@936: import org.jfree.chart.ChartPanel;
sascha@936: 
sascha@938: import org.jfree.chart.axis.NumberAxis;
sascha@938: 
sascha@936: import org.jfree.data.xy.XYDataset;
sascha@936: import org.jfree.data.xy.DefaultXYDataset;
sascha@936: 
sascha@936: import de.intevation.flys.model.CrossSection;
sascha@936: import de.intevation.flys.model.CrossSectionLine;
sascha@936: import de.intevation.flys.model.CrossSectionPoint;
sascha@936: 
sascha@938: import de.intevation.flys.geom.Lines;
sascha@938: 
sascha@936: import de.intevation.flys.backend.SessionFactoryProvider;
sascha@936: 
sascha@936: import org.hibernate.Session;
sascha@936: import org.hibernate.Query;
sascha@936: 
sascha@936: public class CrossSectionApp
sascha@936: extends      ApplicationFrame
sascha@936: {
felix@1122:     public static final String RIVER = System.getProperty("river", "Saar");
sascha@936: 
sascha@936:     public static final double EPSILON   = 1e-4;
sascha@936: 
sascha@936:     protected Session session;
sascha@936: 
sascha@936:     protected JComboBox crossSectionsCB;
sascha@936:     protected JComboBox crossSectionLinesCB;
sascha@938:     protected JTextField waterlevelTF;
sascha@936: 
sascha@936:     protected ChartPanel chartPanel;
sascha@936: 
sascha@938:     protected Double lastWaterLevel;
sascha@938: 
sascha@936: 
sascha@936:     public static class CrossSectionItem {
sascha@936: 
sascha@936:         CrossSection crossSection;
sascha@936: 
sascha@936:         public CrossSectionItem(CrossSection crossSection) {
sascha@936:             this.crossSection = crossSection;
sascha@936:         }
sascha@936: 
sascha@936:         public String toString() {
sascha@936:             return crossSection.getDescription();
sascha@936:         }
sascha@936:     } // CrossSectionItem
sascha@936: 
sascha@936:     public static class CrossSectionLineItem {
sascha@936: 
sascha@936:         CrossSectionLine line;
sascha@936: 
sascha@936:         public CrossSectionLineItem(CrossSectionLine line) {
sascha@936:             this.line = line;
sascha@936:         }
sascha@936: 
sascha@936:         public String toString() {
sascha@936:             double v = line.getKm().doubleValue();
sascha@936:             return String.valueOf(Math.round(v * 1000.0)/1000d);
sascha@936:         }
sascha@936:     } // CrossSectionLineItem
sascha@936: 
sascha@936:     public CrossSectionApp(String title) {
sascha@936:         super(title);
sascha@936: 
sascha@936:         session = SessionFactoryProvider
sascha@936:             .createSessionFactory()
sascha@936:             .openSession();
sascha@936: 
sascha@936:         JPanel content = createContent();
sascha@936:         content.setPreferredSize(new Dimension(640, 480));
sascha@936:         setContentPane(content);
sascha@936: 
sascha@936:     }
sascha@936: 
sascha@936:     public List<CrossSection> crossSections(String river) {
sascha@936:         Query query = session.createQuery(
sascha@936:             "from CrossSection where river.name = :river");
sascha@936:         query.setParameter("river", river);
sascha@936:         return query.list();
sascha@936:     }
sascha@936: 
sascha@936:     public JPanel createContent() {
sascha@936:         JPanel panel = new JPanel(new BorderLayout());
sascha@936: 
sascha@936: 
sascha@936:         JPanel nav = new JPanel(new FlowLayout());
sascha@936: 
sascha@936:         Object [] csis = createCrossSectionItems();
sascha@936:         crossSectionsCB = new JComboBox(csis);
sascha@936: 
sascha@936:         DefaultComboBoxModel dcbm;
sascha@936: 
sascha@936:         if (csis.length > 0) {
sascha@936:             Object [] cslis =
sascha@936:                 createCrossSectionLineItems(
sascha@936:                     ((CrossSectionItem)csis[0]).crossSection);
sascha@936:             dcbm = new DefaultComboBoxModel(cslis);
sascha@936:             if (cslis.length > 0) {
sascha@936:                 dcbm.setSelectedItem(cslis[0]);
sascha@936:             }
sascha@936:         }
sascha@936:         else {
sascha@936:             dcbm = new DefaultComboBoxModel(new Object[0]);
sascha@936:         }
sascha@936: 
sascha@936:         crossSectionLinesCB = new JComboBox(dcbm);
sascha@936: 
sascha@936:         nav.add(crossSectionsCB);
sascha@936:         nav.add(crossSectionLinesCB);
sascha@936: 
sascha@936:         crossSectionsCB.addItemListener(new ItemListener() {
sascha@936:             public void itemStateChanged(ItemEvent ie) {
sascha@936:                 if (ie.getStateChange() == ItemEvent.SELECTED) {
sascha@936:                     updateCrossSection(
sascha@936:                         ((CrossSectionItem)ie.getItem()).crossSection);
sascha@936:                 }
sascha@936:             }
sascha@936:         });
sascha@936: 
sascha@936:         crossSectionLinesCB.addItemListener(new ItemListener() {
sascha@936:             public void itemStateChanged(ItemEvent ie) {
sascha@936:                 if (ie.getStateChange() == ItemEvent.SELECTED) {
sascha@938:                     updateChart();
sascha@936:                 }
sascha@936:             }
sascha@936:         });
sascha@936: 
sascha@936: 
sascha@938:         waterlevelTF = new JTextField(5);
sascha@936: 
sascha@938:         waterlevelTF.addActionListener(new ActionListener() {
sascha@938:             public void actionPerformed(ActionEvent ae) {
sascha@938:                 waterLevelChanged();
sascha@938:             }
sascha@938:         });
sascha@938: 
sascha@938:         nav.add(waterlevelTF);
sascha@936: 
sascha@936:         JButton dump = new JButton("dump");
sascha@936: 
sascha@936:         dump.addActionListener(new ActionListener() {
sascha@936:             public void actionPerformed(ActionEvent ae) {
sascha@936:                 dumpData();
sascha@936:             }
sascha@936:         });
sascha@936: 
sascha@936:         nav.add(dump);
sascha@936: 
sascha@938:         panel.add(nav, BorderLayout.SOUTH);
sascha@938: 
sascha@938:         chartPanel = createChartPanel();
sascha@938: 
sascha@938:         panel.add(chartPanel, BorderLayout.CENTER);
sascha@938: 
sascha@936:         return panel;
sascha@936:     }
sascha@936: 
sascha@938:     protected void waterLevelChanged() {
sascha@938:         String value = waterlevelTF.getText();
sascha@938:         try {
sascha@938:             lastWaterLevel = Double.parseDouble(value);
sascha@938:         }
sascha@938:         catch (NumberFormatException nfe) {
sascha@938:             waterlevelTF.setText(
sascha@938:                 lastWaterLevel != null ? lastWaterLevel.toString() : "");
sascha@938:             return;
sascha@938:         }
sascha@938:         updateChart();
sascha@938:     }
sascha@938: 
sascha@938:     protected void updateChart() {
sascha@938: 
sascha@938:         CrossSectionLineItem csli =
sascha@938:             (CrossSectionLineItem)crossSectionLinesCB.getSelectedItem();
sascha@938: 
sascha@938:         JFreeChart chart = createChart(csli == null
sascha@938:             ? new DefaultXYDataset()
sascha@938:             : generateDataset(csli.line, lastWaterLevel));
sascha@938: 
sascha@938:         chartPanel.setChart(chart);
sascha@938:     }
sascha@938: 
sascha@936:     protected ChartPanel createChartPanel() {
sascha@936:         CrossSectionLineItem csli =
sascha@936:             (CrossSectionLineItem)crossSectionLinesCB.getSelectedItem();
sascha@936: 
sascha@938:         JFreeChart chart = createChart(csli == null
sascha@938:             ? new DefaultXYDataset()
sascha@938:             : generateDataset(csli.line, lastWaterLevel));
sascha@936: 
sascha@936:         return new ChartPanel(chart);
sascha@936:     }
sascha@936: 
sascha@936:     protected void dumpData() {
sascha@936: 
sascha@936:         CrossSectionLineItem csli =
sascha@936:             (CrossSectionLineItem)crossSectionLinesCB.getSelectedItem();
sascha@936: 
sascha@936:         if (csli == null) {
sascha@936:             return;
sascha@936:         }
sascha@936: 
sascha@936:         CrossSectionLine line = csli.line;
sascha@936: 
sascha@936:         double km = Math.round(line.getKm().doubleValue() * 1000d)/1000d;
sascha@936: 
sascha@936:         String kmS = String.valueOf(km).replace(".", "-");
sascha@936: 
sascha@936:         int i = 1;
sascha@936:         File file = new File("cross-section-" + kmS + ".txt");
sascha@936:         while (file.exists()) {
sascha@936:             file = new File("cross-section-" + kmS + "[" + (i++) + "].txt");
sascha@936:         }
sascha@936: 
sascha@936:         System.err.println("dump points to file '" + file + "'");
sascha@936: 
sascha@936:         List<CrossSectionPoint> points = line.getPoints();
sascha@936: 
sascha@936:         PrintWriter out = null;
sascha@936: 
sascha@936:         MathContext mc = new MathContext(3);
sascha@936: 
sascha@936:         try {
sascha@936:             out =
sascha@936:                 new PrintWriter(
sascha@936:                 new FileWriter(file));
sascha@936: 
sascha@936:             for (CrossSectionPoint point: points) {
sascha@936:                 out.println(
sascha@936:                     point.getX().round(mc) + " " +
sascha@936:                     point.getY().round(mc));
sascha@936:             }
sascha@936: 
sascha@936:             out.flush();
sascha@936:         }
sascha@936:         catch (IOException ioe) {
sascha@936:             ioe.printStackTrace();
sascha@936:         }
sascha@936:         finally {
sascha@936:             if (out != null) {
sascha@936:                 out.close();
sascha@936:             }
sascha@936:         }
sascha@936:     }
sascha@936: 
felix@1122:     public static XYDataset generateDataset(
sascha@938:         CrossSectionLine line,
sascha@938:         Double           waterlevel
sascha@938:     ) {
sascha@936:         DefaultXYDataset dataset = new DefaultXYDataset();
sascha@936: 
sascha@1651:         List<Point2D> points = line.fetchCrossSectionLinesPoints();
sascha@936: 
sascha@936:         if (points.isEmpty()) {
sascha@936:             return dataset;
sascha@936:         }
sascha@936: 
sascha@938:         if (waterlevel != null) {
sascha@1651:             double [][] data = Lines.createWaterLines(points, waterlevel);
sascha@938:             dataset.addSeries(String.valueOf(waterlevel), data);
sascha@938:         }
sascha@938: 
sascha@936:         CrossSection cs = line.getCrossSection();
sascha@936: 
sascha@936:         String legend = (cs != null ? cs.getDescription() : "???")
sascha@936:             + " " + Math.round(line.getKm().doubleValue() * 1000d)/1000d;
sascha@936: 
sascha@1651:         double [][] values = CrossSectionLine.fetchCrossSectionProfile(points);
sascha@1651: 
sascha@1651:         dataset.addSeries(legend, values);
sascha@936: 
sascha@936:         return dataset;
sascha@936:     }
sascha@936: 
sascha@936:     protected void updateCrossSection(CrossSection crossSection) {
sascha@936:         Object [] cslis = createCrossSectionLineItems(crossSection);
sascha@936:         DefaultComboBoxModel dcbm = new DefaultComboBoxModel(cslis);
sascha@936:         if (cslis.length > 0) {
sascha@936:             dcbm.setSelectedItem(cslis[0]);
sascha@936:         }
sascha@936:         crossSectionLinesCB.setModel(dcbm);
sascha@936:         if (cslis.length > 0) {
sascha@936:             CrossSectionLine line =
sascha@936:                 ((CrossSectionLineItem)cslis[0]).line;
sascha@936:         }
sascha@938:         updateChart();
sascha@936:     }
sascha@936: 
sascha@936:     protected Object [] createCrossSectionLineItems(CrossSection cs) {
sascha@936:         List<CrossSectionLine> lines = cs.getLines();
sascha@936:         Object [] result = new Object[lines.size()];
sascha@936:         for (int i = 0; i < result.length; ++i) {
sascha@936:             result[i] = new CrossSectionLineItem(lines.get(i));
sascha@936:         }
sascha@936:         return result;
sascha@936:     }
sascha@936: 
sascha@936: 
sascha@936:     protected Object [] createCrossSectionItems() {
sascha@936:         List<CrossSection> crossSections = crossSections(RIVER);
sascha@936:         Object [] result = new Object[crossSections.size()];
sascha@936:         for (int i = 0; i < result.length; ++i) {
sascha@936:             result[i] = new CrossSectionItem(crossSections.get(i));
sascha@936:         }
sascha@936:         return result;
sascha@936:     }
sascha@936: 
sascha@936:     public static JFreeChart createChart(XYDataset dataset) {
sascha@936:         JFreeChart chart = ChartFactory.createXYLineChart(
sascha@936:             null,
sascha@936:             "Abstand [m]",
sascha@936:             "H\u00f6he [m]",
sascha@936:             dataset,
sascha@936:             PlotOrientation.VERTICAL,
sascha@936:             true,
sascha@936:             true,
sascha@936:             false);
sascha@938: 
sascha@938:         XYPlot plot = chart.getXYPlot();
sascha@938:         NumberAxis yAxis = (NumberAxis)plot.getRangeAxis();
sascha@938:         yAxis.setAutoRangeIncludesZero(false);
sascha@938: 
sascha@936:         ChartUtilities.applyCurrentTheme(chart);
sascha@936:         return chart;
sascha@936:     }
sascha@936: 
sascha@936:     public static void main(String [] args) {
sascha@936:         CrossSectionApp csa = new CrossSectionApp("Querprofile");
sascha@936:         csa.pack();
sascha@936:         RefineryUtilities.centerFrameOnScreen(csa);
sascha@936:         csa.setVisible(true);
sascha@936:     }
sascha@936: }
sascha@936: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :