comparison flys-artifacts/src/main/java/de/intevation/flys/artifacts/charts/CrossSectionApp.java @ 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
children bd3683453928
comparison
equal deleted inserted replaced
935:353ddfa231a7 936:759808931a2e
1 package de.intevation.flys.artifacts.charts;
2
3 import java.math.MathContext;
4
5 import java.awt.Dimension;
6 import java.awt.BorderLayout;
7 import java.awt.FlowLayout;
8
9 import javax.swing.JPanel;
10 import javax.swing.JButton;
11 import javax.swing.JComboBox;
12 import javax.swing.DefaultComboBoxModel;
13
14 import java.awt.event.ItemListener;
15 import java.awt.event.ItemEvent;
16 import java.awt.event.ActionListener;
17 import java.awt.event.ActionEvent;
18
19 import java.util.ArrayList;
20 import java.util.List;
21 import java.util.Comparator;
22 import java.util.Collections;
23
24 import java.io.File;
25 import java.io.IOException;
26 import java.io.FileWriter;
27 import java.io.PrintWriter;
28
29 import org.jfree.ui.ApplicationFrame;
30 import org.jfree.ui.RefineryUtilities;
31
32 import org.jfree.chart.ChartFactory;
33
34 import org.jfree.chart.plot.PlotOrientation;
35
36 import org.jfree.chart.ChartUtilities;
37 import org.jfree.chart.JFreeChart;
38 import org.jfree.chart.ChartPanel;
39
40 import org.jfree.data.xy.XYDataset;
41 import org.jfree.data.xy.DefaultXYDataset;
42
43 import de.intevation.flys.model.CrossSection;
44 import de.intevation.flys.model.CrossSectionLine;
45 import de.intevation.flys.model.CrossSectionPoint;
46
47 import de.intevation.flys.backend.SessionFactoryProvider;
48
49 import org.hibernate.Session;
50 import org.hibernate.Query;
51
52
53 public class CrossSectionApp
54 extends ApplicationFrame
55 {
56 public static final String RIVER = System.getProperty("river", "Mosel");
57
58 public static final double EPSILON = 1e-4;
59
60 public static final double TOO_SMALL = 0.2;
61 public static final double TOO_BIG = 4000;
62
63 public static final Comparator<CrossSectionPoint> COL_POS_CMP =
64 new Comparator<CrossSectionPoint>() {
65 @Override
66 public int compare(CrossSectionPoint a, CrossSectionPoint b) {
67 double xa = a.getX().doubleValue();
68 double xb = b.getX().doubleValue();
69 double d = xa - xb;
70 if (d < -EPSILON) return -1;
71 if (d > +EPSILON) return +1;
72 int diff = a.getColPos() - b.getColPos();
73 return diff < 0 ? -1 : diff > 0 ? +1 : 0;
74 }
75 };
76
77 public static final boolean isValid(double x) {
78 x = Math.abs(x);
79 return x > TOO_SMALL && x < TOO_BIG;
80 }
81
82 protected Session session;
83
84 protected JComboBox crossSectionsCB;
85 protected JComboBox crossSectionLinesCB;
86
87 protected ChartPanel chartPanel;
88
89
90 public static class CrossSectionItem {
91
92 CrossSection crossSection;
93
94 public CrossSectionItem(CrossSection crossSection) {
95 this.crossSection = crossSection;
96 }
97
98 public String toString() {
99 return crossSection.getDescription();
100 }
101 } // CrossSectionItem
102
103 public static class CrossSectionLineItem {
104
105 CrossSectionLine line;
106
107 public CrossSectionLineItem(CrossSectionLine line) {
108 this.line = line;
109 }
110
111 public String toString() {
112 double v = line.getKm().doubleValue();
113 return String.valueOf(Math.round(v * 1000.0)/1000d);
114 }
115 } // CrossSectionLineItem
116
117 public CrossSectionApp(String title) {
118 super(title);
119
120 session = SessionFactoryProvider
121 .createSessionFactory()
122 .openSession();
123
124 JPanel content = createContent();
125 content.setPreferredSize(new Dimension(640, 480));
126 setContentPane(content);
127
128 }
129
130 public List<CrossSection> crossSections(String river) {
131 Query query = session.createQuery(
132 "from CrossSection where river.name = :river");
133 query.setParameter("river", river);
134 return query.list();
135 }
136
137 public JPanel createContent() {
138 JPanel panel = new JPanel(new BorderLayout());
139
140
141 JPanel nav = new JPanel(new FlowLayout());
142
143 Object [] csis = createCrossSectionItems();
144 crossSectionsCB = new JComboBox(csis);
145
146 DefaultComboBoxModel dcbm;
147
148 if (csis.length > 0) {
149 Object [] cslis =
150 createCrossSectionLineItems(
151 ((CrossSectionItem)csis[0]).crossSection);
152 dcbm = new DefaultComboBoxModel(cslis);
153 if (cslis.length > 0) {
154 dcbm.setSelectedItem(cslis[0]);
155 }
156 }
157 else {
158 dcbm = new DefaultComboBoxModel(new Object[0]);
159 }
160
161 crossSectionLinesCB = new JComboBox(dcbm);
162
163 nav.add(crossSectionsCB);
164 nav.add(crossSectionLinesCB);
165
166 crossSectionsCB.addItemListener(new ItemListener() {
167 public void itemStateChanged(ItemEvent ie) {
168 if (ie.getStateChange() == ItemEvent.SELECTED) {
169 updateCrossSection(
170 ((CrossSectionItem)ie.getItem()).crossSection);
171 }
172 }
173 });
174
175 crossSectionLinesCB.addItemListener(new ItemListener() {
176 public void itemStateChanged(ItemEvent ie) {
177 if (ie.getStateChange() == ItemEvent.SELECTED) {
178 updateCrossSectionLine(((CrossSectionLineItem)ie.getItem()).line);
179 }
180 }
181 });
182
183 panel.add(nav, BorderLayout.SOUTH);
184
185 chartPanel = createChartPanel();
186
187 panel.add(chartPanel, BorderLayout.CENTER);
188
189 JButton dump = new JButton("dump");
190
191 dump.addActionListener(new ActionListener() {
192 public void actionPerformed(ActionEvent ae) {
193 dumpData();
194 }
195 });
196
197 nav.add(dump);
198
199 return panel;
200 }
201
202 protected ChartPanel createChartPanel() {
203 CrossSectionLineItem csli =
204 (CrossSectionLineItem)crossSectionLinesCB.getSelectedItem();
205
206 if (csli == null) {
207 return new ChartPanel(null);
208 }
209
210 XYDataset dataset = crossSectionPoints(csli.line);
211
212 JFreeChart chart = createChart(dataset);
213
214 return new ChartPanel(chart);
215 }
216
217 protected void updateCrossSectionLine(CrossSectionLine line) {
218 XYDataset dataset = crossSectionPoints(line);
219 JFreeChart chart = createChart(dataset);
220 chartPanel.setChart(chart);
221 }
222
223 protected void dumpData() {
224
225 CrossSectionLineItem csli =
226 (CrossSectionLineItem)crossSectionLinesCB.getSelectedItem();
227
228 if (csli == null) {
229 return;
230 }
231
232 CrossSectionLine line = csli.line;
233
234 double km = Math.round(line.getKm().doubleValue() * 1000d)/1000d;
235
236 String kmS = String.valueOf(km).replace(".", "-");
237
238 int i = 1;
239 File file = new File("cross-section-" + kmS + ".txt");
240 while (file.exists()) {
241 file = new File("cross-section-" + kmS + "[" + (i++) + "].txt");
242 }
243
244 System.err.println("dump points to file '" + file + "'");
245
246 List<CrossSectionPoint> points = line.getPoints();
247
248 PrintWriter out = null;
249
250 MathContext mc = new MathContext(3);
251
252 try {
253 out =
254 new PrintWriter(
255 new FileWriter(file));
256
257 for (CrossSectionPoint point: points) {
258 out.println(
259 point.getX().round(mc) + " " +
260 point.getY().round(mc));
261 }
262
263 out.flush();
264 }
265 catch (IOException ioe) {
266 ioe.printStackTrace();
267 }
268 finally {
269 if (out != null) {
270 out.close();
271 }
272 }
273 }
274
275 protected XYDataset crossSectionPoints(CrossSectionLine line) {
276 DefaultXYDataset dataset = new DefaultXYDataset();
277
278 List<CrossSectionPoint> ps = line.getPoints();
279
280 List<CrossSectionPoint> points =
281 new ArrayList<CrossSectionPoint>(ps.size());
282
283 for (CrossSectionPoint p: ps) {
284 if (isValid(p.getX().doubleValue())
285 && isValid(p.getY().doubleValue())) {
286 points.add(p);
287 }
288 }
289
290 if (points.isEmpty()) {
291 return dataset;
292 }
293
294 Collections.sort(points, COL_POS_CMP);
295
296 double [] xs = new double[points.size()];
297 double [] ys = new double[xs.length];
298
299 double x = points.get(0).getX().doubleValue();
300 double y = points.get(0).getY().doubleValue();
301
302 xs[0] = x;
303 ys[0] = y;
304
305 for (int i = 1; i < xs.length; ++i) {
306 CrossSectionPoint p = points.get(i);
307 x = p.getX().doubleValue();
308 y = p.getY().doubleValue();
309
310 if (x <= xs[i-1]) {
311 x = xs[i-1] + EPSILON;
312 }
313 xs[i] = x;
314 ys[i] = y;
315 }
316
317 CrossSection cs = line.getCrossSection();
318
319 String legend = (cs != null ? cs.getDescription() : "???")
320 + " " + Math.round(line.getKm().doubleValue() * 1000d)/1000d;
321
322 dataset.addSeries(legend, new double [][] { xs, ys });
323
324 return dataset;
325 }
326
327 protected void updateCrossSection(CrossSection crossSection) {
328 Object [] cslis = createCrossSectionLineItems(crossSection);
329 DefaultComboBoxModel dcbm = new DefaultComboBoxModel(cslis);
330 if (cslis.length > 0) {
331 dcbm.setSelectedItem(cslis[0]);
332 }
333 crossSectionLinesCB.setModel(dcbm);
334 if (cslis.length > 0) {
335 CrossSectionLine line =
336 ((CrossSectionLineItem)cslis[0]).line;
337 updateCrossSectionLine(line);
338 }
339 }
340
341 protected Object [] createCrossSectionLineItems(CrossSection cs) {
342 List<CrossSectionLine> lines = cs.getLines();
343 Object [] result = new Object[lines.size()];
344 for (int i = 0; i < result.length; ++i) {
345 result[i] = new CrossSectionLineItem(lines.get(i));
346 }
347 return result;
348 }
349
350
351 protected Object [] createCrossSectionItems() {
352 List<CrossSection> crossSections = crossSections(RIVER);
353 Object [] result = new Object[crossSections.size()];
354 for (int i = 0; i < result.length; ++i) {
355 result[i] = new CrossSectionItem(crossSections.get(i));
356 }
357 return result;
358 }
359
360 public static JFreeChart createChart(XYDataset dataset) {
361 JFreeChart chart = ChartFactory.createXYLineChart(
362 null,
363 "Abstand [m]",
364 "H\u00f6he [m]",
365 dataset,
366 PlotOrientation.VERTICAL,
367 true,
368 true,
369 false);
370 ChartUtilities.applyCurrentTheme(chart);
371 return chart;
372 }
373
374 public static void main(String [] args) {
375 CrossSectionApp csa = new CrossSectionApp("Querprofile");
376 csa.pack();
377 RefineryUtilities.centerFrameOnScreen(csa);
378 csa.setVisible(true);
379 }
380 }
381 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org