changeset 936:759808931a2e

Add Swing standalone app to test/develope cross sections directly from database. flys-artifacts/trunk@2328 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Wed, 13 Jul 2011 17:33:15 +0000
parents 353ddfa231a7
children 9e813e9137a5
files flys-artifacts/ChangeLog flys-artifacts/src/main/java/de/intevation/flys/artifacts/charts/CrossSectionApp.java flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WSPLGENFacet.java
diffstat 3 files changed, 400 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/flys-artifacts/ChangeLog	Wed Jul 13 10:29:32 2011 +0000
+++ b/flys-artifacts/ChangeLog	Wed Jul 13 17:33:15 2011 +0000
@@ -1,3 +1,22 @@
+2011-07-13  Sascha L. Teichmann <sascha.teichmann@intevation.de>
+
+	* src/main/java/de/intevation/flys/artifacts/charts/CrossSectionApp.java:
+	  New. Standalone Swing-App to test cross sections from database without the
+	  hassles of our complete software stack. Runnable from a maven environment:
+
+	  $ mvn -e \
+	    -Dflys.backend.user=DB_USER \
+		-Dflys.backend.password=DB_PASSWD \
+		-Dflys.backend.url=DB_CONNECTION_URL \
+		-Dexec.mainClass=de.intevation.flys.artifacts.charts.CrossSectionApp \
+		exec:java
+
+	  You can set the river to be used with the system property 'river'.
+	  Defaults to 'Mosel'.
+
+	* src/main/java/de/intevation/flys/artifacts/model/WSPLGENFacet.java:
+	  Removed superfluous imports.
+
 2011-07-13  Ingo Weinzierl <ingo@intevation.de>
 
 	* doc/conf/artifacts/winfo.xml: The FloodMapState has a new Outputmode
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/charts/CrossSectionApp.java	Wed Jul 13 17:33:15 2011 +0000
@@ -0,0 +1,381 @@
+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.DefaultComboBoxModel;
+
+import java.awt.event.ItemListener;
+import java.awt.event.ItemEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.ActionEvent;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Comparator;
+import java.util.Collections;
+
+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.ChartUtilities;
+import org.jfree.chart.JFreeChart;
+import org.jfree.chart.ChartPanel;
+
+import org.jfree.data.xy.XYDataset;
+import org.jfree.data.xy.DefaultXYDataset;
+
+import de.intevation.flys.model.CrossSection;
+import de.intevation.flys.model.CrossSectionLine;
+import de.intevation.flys.model.CrossSectionPoint;
+
+import de.intevation.flys.backend.SessionFactoryProvider;
+
+import org.hibernate.Session;
+import org.hibernate.Query;
+
+
+public class CrossSectionApp
+extends      ApplicationFrame
+{
+    public static final String RIVER = System.getProperty("river", "Mosel");
+
+    public static final double EPSILON   = 1e-4;
+
+    public static final double TOO_SMALL = 0.2;
+    public static final double TOO_BIG   = 4000;
+
+    public static final Comparator<CrossSectionPoint> COL_POS_CMP =
+        new Comparator<CrossSectionPoint>() {
+            @Override
+            public int compare(CrossSectionPoint a, CrossSectionPoint b) {
+                double xa = a.getX().doubleValue();
+                double xb = b.getX().doubleValue();
+                double d = xa - xb;
+                if (d < -EPSILON) return -1;
+                if (d > +EPSILON) return +1;
+                int diff = a.getColPos() - b.getColPos();
+                return diff < 0 ? -1 : diff > 0 ? +1 : 0;
+            }
+        };
+
+    public static final boolean isValid(double x) {
+        x = Math.abs(x);
+        return x > TOO_SMALL && x < TOO_BIG;
+    }
+
+    protected Session session;
+
+    protected JComboBox crossSectionsCB;
+    protected JComboBox crossSectionLinesCB;
+
+    protected ChartPanel chartPanel;
+
+
+    public static class CrossSectionItem {
+
+        CrossSection crossSection;
+
+        public CrossSectionItem(CrossSection crossSection) {
+            this.crossSection = crossSection;
+        }
+
+        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);
+        }
+    } // CrossSectionLineItem
+
+    public CrossSectionApp(String title) {
+        super(title);
+
+        session = SessionFactoryProvider
+            .createSessionFactory()
+            .openSession();
+
+        JPanel content = createContent();
+        content.setPreferredSize(new Dimension(640, 480));
+        setContentPane(content);
+
+    }
+
+    public List<CrossSection> crossSections(String river) {
+        Query query = session.createQuery(
+            "from CrossSection where river.name = :river");
+        query.setParameter("river", river);
+        return query.list();
+    }
+
+    public JPanel createContent() {
+        JPanel panel = new JPanel(new BorderLayout());
+
+
+        JPanel nav = new JPanel(new FlowLayout());
+
+        Object [] csis = createCrossSectionItems();
+        crossSectionsCB = new JComboBox(csis);
+
+        DefaultComboBoxModel dcbm;
+
+        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]);
+        }
+
+        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() {
+            public void itemStateChanged(ItemEvent ie) {
+                if (ie.getStateChange() == ItemEvent.SELECTED) {
+                    updateCrossSectionLine(((CrossSectionLineItem)ie.getItem()).line);
+                }
+            }
+        });
+
+        panel.add(nav, BorderLayout.SOUTH);
+
+        chartPanel = createChartPanel();
+
+        panel.add(chartPanel, BorderLayout.CENTER);
+
+        JButton dump = new JButton("dump");
+
+        dump.addActionListener(new ActionListener() {
+            public void actionPerformed(ActionEvent ae) {
+                dumpData();
+            }
+        });
+
+        nav.add(dump);
+
+        return panel;
+    }
+
+    protected ChartPanel createChartPanel() {
+        CrossSectionLineItem csli =
+            (CrossSectionLineItem)crossSectionLinesCB.getSelectedItem();
+
+        if (csli == null) {
+            return new ChartPanel(null);
+        }
+
+        XYDataset dataset = crossSectionPoints(csli.line);
+
+        JFreeChart chart = createChart(dataset);
+
+        return new ChartPanel(chart);
+    }
+
+    protected void updateCrossSectionLine(CrossSectionLine line) {
+        XYDataset dataset = crossSectionPoints(line);
+        JFreeChart chart = createChart(dataset);
+        chartPanel.setChart(chart);
+    }
+
+    protected void dumpData() {
+
+        CrossSectionLineItem csli =
+            (CrossSectionLineItem)crossSectionLinesCB.getSelectedItem();
+
+        if (csli == null) {
+            return;
+        }
+
+        CrossSectionLine line = csli.line;
+
+        double km = Math.round(line.getKm().doubleValue() * 1000d)/1000d;
+
+        String kmS = String.valueOf(km).replace(".", "-");
+
+        int i = 1;
+        File file = new File("cross-section-" + kmS + ".txt");
+        while (file.exists()) {
+            file = new File("cross-section-" + kmS + "[" + (i++) + "].txt");
+        }
+
+        System.err.println("dump points to file '" + file + "'");
+
+        List<CrossSectionPoint> points = line.getPoints();
+
+        PrintWriter out = null;
+
+        MathContext mc = new MathContext(3);
+
+        try {
+            out =
+                new PrintWriter(
+                new FileWriter(file));
+
+            for (CrossSectionPoint point: points) {
+                out.println(
+                    point.getX().round(mc) + " " +
+                    point.getY().round(mc));
+            }
+
+            out.flush();
+        }
+        catch (IOException ioe) {
+            ioe.printStackTrace();
+        }
+        finally {
+            if (out != null) {
+                out.close();
+            }
+        }
+    }
+
+    protected XYDataset crossSectionPoints(CrossSectionLine line) {
+        DefaultXYDataset dataset = new DefaultXYDataset();
+
+        List<CrossSectionPoint> ps = line.getPoints();
+
+        List<CrossSectionPoint> points =
+            new ArrayList<CrossSectionPoint>(ps.size());
+
+        for (CrossSectionPoint p: ps) {
+            if (isValid(p.getX().doubleValue())
+            &&  isValid(p.getY().doubleValue())) {
+                points.add(p);
+            }
+        }
+
+        if (points.isEmpty()) {
+            return dataset;
+        }
+
+        Collections.sort(points, COL_POS_CMP);
+
+        double [] xs = new double[points.size()];
+        double [] ys = new double[xs.length];
+
+        double x = points.get(0).getX().doubleValue();
+        double y = points.get(0).getY().doubleValue();
+
+        xs[0] = x;
+        ys[0] = y;
+
+        for (int i = 1; i < xs.length; ++i) {
+            CrossSectionPoint p = points.get(i);
+            x = p.getX().doubleValue();
+            y = p.getY().doubleValue();
+
+            if (x <= xs[i-1]) {
+                x = xs[i-1] + EPSILON;
+            }
+            xs[i] = x;
+            ys[i] = y;
+        }
+
+        CrossSection cs = line.getCrossSection();
+
+        String legend = (cs != null ? cs.getDescription() : "???")
+            + " " + Math.round(line.getKm().doubleValue() * 1000d)/1000d;
+
+        dataset.addSeries(legend, new double [][] { xs, ys });
+
+        return dataset;
+    }
+
+    protected void updateCrossSection(CrossSection crossSection) {
+        Object [] cslis = createCrossSectionLineItems(crossSection);
+        DefaultComboBoxModel dcbm = new DefaultComboBoxModel(cslis);
+        if (cslis.length > 0) {
+            dcbm.setSelectedItem(cslis[0]);
+        }
+        crossSectionLinesCB.setModel(dcbm);
+        if (cslis.length > 0) {
+            CrossSectionLine line =
+                ((CrossSectionLineItem)cslis[0]).line;
+            updateCrossSectionLine(line);
+        }
+    }
+
+    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));
+        }
+        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) {
+        JFreeChart chart = ChartFactory.createXYLineChart(
+            null,
+            "Abstand [m]",
+            "H\u00f6he [m]",
+            dataset,
+            PlotOrientation.VERTICAL,
+            true,
+            true,
+            false);
+        ChartUtilities.applyCurrentTheme(chart);
+        return chart;
+    }
+
+    public static void main(String [] args) {
+        CrossSectionApp csa = new CrossSectionApp("Querprofile");
+        csa.pack();
+        RefineryUtilities.centerFrameOnScreen(csa);
+        csa.setVisible(true);
+    }
+}
+// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WSPLGENFacet.java	Wed Jul 13 10:29:32 2011 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WSPLGENFacet.java	Wed Jul 13 17:33:15 2011 +0000
@@ -1,13 +1,7 @@
 package de.intevation.flys.artifacts.model;
 
-import org.apache.log4j.Logger;
-
-import de.intevation.artifacts.Artifact;
-import de.intevation.artifacts.CallContext;
-
 import de.intevation.artifactdatabase.state.DefaultFacet;
 
-
 public class WSPLGENFacet extends DefaultFacet {
 
     public WSPLGENFacet(int idx, String name, String description) {

http://dive4elements.wald.intevation.org