Mercurial > dive4elements > river
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) {