comparison flys-artifacts/src/main/java/de/intevation/flys/artifacts/charts/CrossSectionApp.java @ 1817:595c404523a6

Rewritten CrossSectionApp to be useful as test bed for 'Raum/Flaeche' operations. flys-artifacts/trunk@3146 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Thu, 03 Nov 2011 09:47:52 +0000
parents a7def20539fb
children d562772a418e
comparison
equal deleted inserted replaced
1816:5364b86a0880 1817:595c404523a6
1 package de.intevation.flys.artifacts.charts; 1 package de.intevation.flys.artifacts.charts;
2 2
3 import java.math.MathContext; 3 import de.intevation.flys.backend.SessionFactoryProvider;
4 4
5 import java.awt.Dimension; 5 import de.intevation.flys.geom.Lines;
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.JTextField;
13 import javax.swing.DefaultComboBoxModel;
14
15 import java.awt.event.ItemListener;
16 import java.awt.event.ItemEvent;
17 import java.awt.event.ActionListener;
18 import java.awt.event.ActionEvent;
19
20 import java.awt.geom.Point2D;
21
22 import java.util.List;
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 import org.jfree.chart.plot.XYPlot;
36
37 import org.jfree.chart.ChartUtilities;
38 import org.jfree.chart.JFreeChart;
39 import org.jfree.chart.ChartPanel;
40
41 import org.jfree.chart.axis.NumberAxis;
42
43 import org.jfree.data.xy.XYDataset;
44 import org.jfree.data.xy.DefaultXYDataset;
45 6
46 import de.intevation.flys.model.CrossSection; 7 import de.intevation.flys.model.CrossSection;
47 import de.intevation.flys.model.CrossSectionLine; 8 import de.intevation.flys.model.CrossSectionLine;
48 import de.intevation.flys.model.CrossSectionPoint; 9 import de.intevation.flys.model.CrossSectionPoint;
49 10
50 import de.intevation.flys.geom.Lines; 11 import de.intevation.flys.utils.Pair;
51 12
52 import de.intevation.flys.backend.SessionFactoryProvider; 13 import java.awt.BorderLayout;
53 14 import java.awt.Dimension;
15 import java.awt.FlowLayout;
16
17 import java.awt.event.ActionEvent;
18 import java.awt.event.ActionListener;
19 import java.awt.event.ItemEvent;
20 import java.awt.event.ItemListener;
21
22 import java.awt.geom.Point2D;
23
24 import java.io.File;
25 import java.io.FileWriter;
26 import java.io.IOException;
27 import java.io.PrintWriter;
28
29 import java.math.MathContext;
30
31 import java.util.ArrayList;
32 import java.util.Arrays;
33 import java.util.List;
34 import java.util.Map;
35 import java.util.TreeMap;
36
37 import javax.swing.DefaultComboBoxModel;
38 import javax.swing.JButton;
39 import javax.swing.JComboBox;
40 import javax.swing.JPanel;
41 import javax.swing.JScrollPane;
42 import javax.swing.JTable;
43 import javax.swing.JTextField;
44
45 import javax.swing.event.TableModelEvent;
46 import javax.swing.event.TableModelListener;
47
48 import javax.swing.table.AbstractTableModel;
49
50 import org.hibernate.Query;
54 import org.hibernate.Session; 51 import org.hibernate.Session;
55 import org.hibernate.Query; 52
53 import org.jfree.chart.ChartFactory;
54 import org.jfree.chart.ChartPanel;
55 import org.jfree.chart.ChartUtilities;
56 import org.jfree.chart.JFreeChart;
57
58 import org.jfree.chart.axis.NumberAxis;
59
60 import org.jfree.chart.plot.PlotOrientation;
61 import org.jfree.chart.plot.XYPlot;
62
63 import org.jfree.data.xy.DefaultXYDataset;
64 import org.jfree.data.xy.XYDataset;
65 import org.jfree.data.xy.XYSeries;
66 import org.jfree.data.xy.XYSeriesCollection;
67
68 import org.jfree.ui.ApplicationFrame;
69 import org.jfree.ui.RefineryUtilities;
56 70
57 public class CrossSectionApp 71 public class CrossSectionApp
58 extends ApplicationFrame 72 extends ApplicationFrame
59 { 73 {
60 public static final String RIVER = System.getProperty("river", "Saar"); 74 public static final String RIVER = System.getProperty("river", "Saar");
61 75
62 public static final double EPSILON = 1e-4; 76 public static final double EPSILON = 1e-4;
63 77
64 protected Session session; 78 protected Session session;
65 79
66 protected JComboBox crossSectionsCB;
67 protected JComboBox crossSectionLinesCB; 80 protected JComboBox crossSectionLinesCB;
68 protected JTextField waterlevelTF; 81 protected JTextField waterlevelTF;
69 82
70 protected ChartPanel chartPanel; 83 protected ChartPanel chartPanel;
71 84
72 protected Double lastWaterLevel; 85 protected Double lastWaterLevel;
73 86
74 87 protected List<CrossSection> crossSections;
75 public static class CrossSectionItem { 88 protected boolean [] drawCrossSection;
76 89 protected boolean [] drawWaterLevel;
77 CrossSection crossSection; 90 protected boolean [] drawGround;
78 91
79 public CrossSectionItem(CrossSection crossSection) { 92 protected Map<Double, List<Pair<CrossSection, CrossSectionLine>>> km2lines;
80 this.crossSection = crossSection; 93
94 public class CrossSectionTableModel extends AbstractTableModel {
95
96 @Override
97 public String getColumnName(int col) {
98 switch (col) {
99 case 0: return "Peilungsname";
100 case 1: return "Peilung";
101 case 2: return "Wasserstand";
102 case 3: return "Boden";
103 }
104 return "";
105 }
106
107 @Override
108 public int getColumnCount() {
109 return 4;
110 }
111
112 @Override
113 public int getRowCount() {
114 return crossSections != null ? crossSections.size() : 0;
115 }
116
117 @Override
118 public Object getValueAt(int row, int col) {
119 if (crossSections == null) return null;
120 switch (col) {
121 case 0: return crossSections.get(row).getDescription();
122 case 1: return drawCrossSection[row];
123 case 2: return drawWaterLevel[row];
124 case 3: return drawGround[row];
125 }
126 return null;
127 }
128
129 @Override
130 public void setValueAt(Object value, int row, int col) {
131 switch (col) {
132 case 1:
133 if (change(drawCrossSection, row, (Boolean)value)) {
134 fireTableCellUpdated(row, col);
135 }
136 break;
137 case 2:
138 if (change(drawWaterLevel, row, (Boolean)value)) {
139 fireTableCellUpdated(row, col);
140 }
141 break;
142 case 3:
143 if (change(drawGround, row, (Boolean)value)) {
144 fireTableCellUpdated(row, col);
145 }
146 break;
147 }
148 }
149
150 @Override
151 public Class<?> getColumnClass(int columnIndex) {
152 switch (columnIndex) {
153 case 0: return String.class;
154 case 1: return Boolean.class;
155 case 2: return Boolean.class;
156 case 3: return Boolean.class;
157 }
158 return null;
159 }
160
161 @Override
162 public boolean isCellEditable(
163 int rowIndex,
164 int columnIndex
165 ) {
166 return columnIndex >= 1 && columnIndex <= 3;
167 }
168 } // class CrossSectionTableModel
169
170 private static boolean change(
171 boolean [] values,
172 int index,
173 boolean value
174 ) {
175 if (values[index] != value) {
176 values[index] = value;
177 return true;
178 }
179 return false;
180 }
181
182 public static class CrossSectionLineItem {
183
184 Double km;
185 List<Pair<CrossSection, CrossSectionLine>> lines;
186
187 public CrossSectionLineItem(
188 Double km,
189 List<Pair<CrossSection, CrossSectionLine>> lines
190 ) {
191 this.km = km;
192 this.lines = lines;
81 } 193 }
82 194
83 public String toString() { 195 public String toString() {
84 return crossSection.getDescription(); 196 return String.valueOf(km);
85 }
86 } // CrossSectionItem
87
88 public static class CrossSectionLineItem {
89
90 CrossSectionLine line;
91
92 public CrossSectionLineItem(CrossSectionLine line) {
93 this.line = line;
94 }
95
96 public String toString() {
97 double v = line.getKm().doubleValue();
98 return String.valueOf(Math.round(v * 1000.0)/1000d);
99 } 197 }
100 } // CrossSectionLineItem 198 } // CrossSectionLineItem
101 199
102 public CrossSectionApp(String title) { 200 public CrossSectionApp(String title) {
103 super(title); 201 super(title);
105 session = SessionFactoryProvider 203 session = SessionFactoryProvider
106 .createSessionFactory() 204 .createSessionFactory()
107 .openSession(); 205 .openSession();
108 206
109 JPanel content = createContent(); 207 JPanel content = createContent();
110 content.setPreferredSize(new Dimension(640, 480)); 208 content.setPreferredSize(new Dimension(800, 480));
111 setContentPane(content); 209 setContentPane(content);
112 210
113 } 211 }
114 212
115 public List<CrossSection> crossSections(String river) { 213 public List<CrossSection> crossSections(String river) {
117 "from CrossSection where river.name = :river"); 215 "from CrossSection where river.name = :river");
118 query.setParameter("river", river); 216 query.setParameter("river", river);
119 return query.list(); 217 return query.list();
120 } 218 }
121 219
220 protected Map<Double, List<Pair<CrossSection, CrossSectionLine>>> loadAllLines(
221 List<CrossSection> crossSections
222 ) {
223 Map<Double, List<Pair<CrossSection, CrossSectionLine>>> km2lines =
224 new TreeMap<Double, List<Pair<CrossSection, CrossSectionLine>>>();
225 for (CrossSection cs: crossSections) {
226 List<CrossSectionLine> lines = cs.getLines();
227 for (CrossSectionLine csl: lines) {
228 Double km = Math.round(csl.getKm().doubleValue() * 1000d)/1000d;
229 List<Pair<CrossSection, CrossSectionLine>> ls = km2lines.get(km);
230 if (ls == null) {
231 ls = new ArrayList<Pair<CrossSection, CrossSectionLine>>(2);
232 km2lines.put(km, ls);
233 }
234 ls.add(new Pair<CrossSection, CrossSectionLine>(cs, csl));
235 }
236 }
237 return km2lines;
238 }
239
122 public JPanel createContent() { 240 public JPanel createContent() {
123 JPanel panel = new JPanel(new BorderLayout()); 241 JPanel panel = new JPanel(new BorderLayout());
124 242
125 243
126 JPanel nav = new JPanel(new FlowLayout()); 244 JPanel nav = new JPanel(new FlowLayout());
127 245
128 Object [] csis = createCrossSectionItems(); 246 crossSections = crossSections(RIVER);
129 crossSectionsCB = new JComboBox(csis); 247 km2lines = loadAllLines(crossSections);
130 248 drawCrossSection = new boolean[crossSections.size()];
131 DefaultComboBoxModel dcbm; 249 Arrays.fill(drawCrossSection, true);
132 250
133 if (csis.length > 0) { 251 drawWaterLevel = new boolean[crossSections.size()];
134 Object [] cslis = 252 drawGround = new boolean[crossSections.size()];
135 createCrossSectionLineItems( 253
136 ((CrossSectionItem)csis[0]).crossSection); 254 Object [] clis = createCrossSectionLineItems(km2lines);
137 dcbm = new DefaultComboBoxModel(cslis); 255
138 if (cslis.length > 0) { 256 DefaultComboBoxModel dcbm = new DefaultComboBoxModel(clis);
139 dcbm.setSelectedItem(cslis[0]);
140 }
141 }
142 else {
143 dcbm = new DefaultComboBoxModel(new Object[0]);
144 }
145 257
146 crossSectionLinesCB = new JComboBox(dcbm); 258 crossSectionLinesCB = new JComboBox(dcbm);
147 259
148 nav.add(crossSectionsCB);
149 nav.add(crossSectionLinesCB); 260 nav.add(crossSectionLinesCB);
150 261
151 crossSectionsCB.addItemListener(new ItemListener() {
152 public void itemStateChanged(ItemEvent ie) {
153 if (ie.getStateChange() == ItemEvent.SELECTED) {
154 updateCrossSection(
155 ((CrossSectionItem)ie.getItem()).crossSection);
156 }
157 }
158 });
159
160 crossSectionLinesCB.addItemListener(new ItemListener() { 262 crossSectionLinesCB.addItemListener(new ItemListener() {
263 @Override
161 public void itemStateChanged(ItemEvent ie) { 264 public void itemStateChanged(ItemEvent ie) {
162 if (ie.getStateChange() == ItemEvent.SELECTED) { 265 if (ie.getStateChange() == ItemEvent.SELECTED) {
163 updateChart(); 266 updateChart();
164 } 267 }
165 } 268 }
166 }); 269 });
167 270
168
169 waterlevelTF = new JTextField(5); 271 waterlevelTF = new JTextField(5);
170 272
171 waterlevelTF.addActionListener(new ActionListener() { 273 waterlevelTF.addActionListener(new ActionListener() {
274 @Override
172 public void actionPerformed(ActionEvent ae) { 275 public void actionPerformed(ActionEvent ae) {
173 waterLevelChanged(); 276 waterLevelChanged();
174 } 277 }
175 }); 278 });
176 279
177 nav.add(waterlevelTF); 280 nav.add(waterlevelTF);
178 281
179 JButton dump = new JButton("dump"); 282 JButton dump = new JButton("dump");
180 283
181 dump.addActionListener(new ActionListener() { 284 dump.addActionListener(new ActionListener() {
285 @Override
182 public void actionPerformed(ActionEvent ae) { 286 public void actionPerformed(ActionEvent ae) {
183 dumpData(); 287 dumpData();
184 } 288 }
185 }); 289 });
186 290
187 nav.add(dump); 291 nav.add(dump);
188 292
189 panel.add(nav, BorderLayout.SOUTH);
190 293
191 chartPanel = createChartPanel(); 294 chartPanel = createChartPanel();
192 295
193 panel.add(chartPanel, BorderLayout.CENTER); 296 panel.add(chartPanel, BorderLayout.CENTER);
297
298
299 CrossSectionTableModel cstm = new CrossSectionTableModel();
300
301 cstm.addTableModelListener(new TableModelListener() {
302 @Override
303 public void tableChanged(TableModelEvent e) {
304 updateChart();
305 }
306 });
307
308 JTable crossTable = new JTable(cstm);
309
310 JPanel west = new JPanel(new BorderLayout());
311 JScrollPane scrollPane = new JScrollPane(crossTable);
312 west.add(scrollPane);
313
314 west.add(nav, BorderLayout.SOUTH);
315
316 panel.add(west, BorderLayout.WEST);
194 317
195 return panel; 318 return panel;
196 } 319 }
197 320
198 protected void waterLevelChanged() { 321 protected void waterLevelChanged() {
212 335
213 CrossSectionLineItem csli = 336 CrossSectionLineItem csli =
214 (CrossSectionLineItem)crossSectionLinesCB.getSelectedItem(); 337 (CrossSectionLineItem)crossSectionLinesCB.getSelectedItem();
215 338
216 JFreeChart chart = createChart(csli == null 339 JFreeChart chart = createChart(csli == null
217 ? new DefaultXYDataset() 340 ? new XYSeriesCollection()
218 : generateDataset(csli.line, lastWaterLevel)); 341 : generateDataset());
219 342
220 chartPanel.setChart(chart); 343 chartPanel.setChart(chart);
221 } 344 }
222 345
223 protected ChartPanel createChartPanel() { 346 protected ChartPanel createChartPanel() {
224 CrossSectionLineItem csli = 347 CrossSectionLineItem csli =
225 (CrossSectionLineItem)crossSectionLinesCB.getSelectedItem(); 348 (CrossSectionLineItem)crossSectionLinesCB.getSelectedItem();
226 349
227 JFreeChart chart = createChart(csli == null 350 JFreeChart chart = createChart(csli == null
228 ? new DefaultXYDataset() 351 ? new XYSeriesCollection()
229 : generateDataset(csli.line, lastWaterLevel)); 352 : generateDataset());
230 353
231 return new ChartPanel(chart); 354 return new ChartPanel(chart);
232 } 355 }
233 356
357 protected void dumpData() {
358 }
359 /*
234 protected void dumpData() { 360 protected void dumpData() {
235 361
236 CrossSectionLineItem csli = 362 CrossSectionLineItem csli =
237 (CrossSectionLineItem)crossSectionLinesCB.getSelectedItem(); 363 (CrossSectionLineItem)crossSectionLinesCB.getSelectedItem();
238 364
280 if (out != null) { 406 if (out != null) {
281 out.close(); 407 out.close();
282 } 408 }
283 } 409 }
284 } 410 }
285 411 */
286 public static XYDataset generateDataset( 412
287 CrossSectionLine line, 413 public void generateWaterLevels(
288 Double waterlevel 414 List<Point2D> points,
415 XYSeriesCollection collection
289 ) { 416 ) {
290 DefaultXYDataset dataset = new DefaultXYDataset(); 417 if (points == null || points.isEmpty()) {
291 418 return;
292 List<Point2D> points = line.fetchCrossSectionLinesPoints(); 419 }
293 420
294 if (points.isEmpty()) { 421 if (lastWaterLevel != null) {
295 return dataset; 422 double [][] data = Lines.createWaterLines(points, lastWaterLevel);
296 } 423 XYSeries series =
297 424 new XYSeries(String.valueOf(lastWaterLevel), false);
298 if (waterlevel != null) { 425
299 double [][] data = Lines.createWaterLines(points, waterlevel); 426 double [] x = data[0];
300 dataset.addSeries(String.valueOf(waterlevel), data); 427 double [] y = data[1];
301 } 428 for (int i = 0; i < x.length; ++i) {
302 429 series.add(x[i], y[i], false);
303 CrossSection cs = line.getCrossSection(); 430 }
304 431
305 String legend = (cs != null ? cs.getDescription() : "???") 432 collection.addSeries(series);
306 + " " + Math.round(line.getKm().doubleValue() * 1000d)/1000d; 433 }
434 }
435
436 public void generateProfile(
437 List<Point2D> points,
438 String legend,
439 XYSeriesCollection collection
440 ) {
441 if (points == null || points.isEmpty()) {
442 return;
443 }
307 444
308 double [][] values = CrossSectionLine.fetchCrossSectionProfile(points); 445 double [][] values = CrossSectionLine.fetchCrossSectionProfile(points);
309 446
310 dataset.addSeries(legend, values); 447 XYSeries series = new XYSeries(legend, false);
311 448
312 return dataset; 449 double [] x = values[0];
313 } 450 double [] y = values[1];
314 451 for (int i = 0; i < x.length; ++i) {
315 protected void updateCrossSection(CrossSection crossSection) { 452 series.add(x[i], y[i], false);
316 Object [] cslis = createCrossSectionLineItems(crossSection); 453 }
317 DefaultComboBoxModel dcbm = new DefaultComboBoxModel(cslis); 454
318 if (cslis.length > 0) { 455 collection.addSeries(series);
319 dcbm.setSelectedItem(cslis[0]); 456 }
320 } 457
321 crossSectionLinesCB.setModel(dcbm); 458 public XYSeriesCollection generateDataset() {
322 if (cslis.length > 0) { 459 XYSeriesCollection collection = new XYSeriesCollection();
323 CrossSectionLine line = 460
324 ((CrossSectionLineItem)cslis[0]).line; 461 CrossSectionLineItem csli =
325 } 462 (CrossSectionLineItem)crossSectionLinesCB.getSelectedItem();
326 updateChart(); 463
327 } 464 for (int i = 0; i < drawCrossSection.length; ++i) {
328 465 List<Point2D> points = null;
329 protected Object [] createCrossSectionLineItems(CrossSection cs) { 466
330 List<CrossSectionLine> lines = cs.getLines(); 467 if (drawCrossSection[i]) {
331 Object [] result = new Object[lines.size()]; 468 CrossSection cs = crossSections.get(i);
332 for (int i = 0; i < result.length; ++i) { 469 for (Pair<CrossSection, CrossSectionLine> csl: csli.lines) {
333 result[i] = new CrossSectionLineItem(lines.get(i)); 470 if (csl.getA() == cs) {
471 points = csl.getB().fetchCrossSectionLinesPoints();
472 generateProfile(
473 points,
474 cs.getDescription(),
475 collection);
476 break;
477 }
478 }
479 }
480
481 if (drawWaterLevel[i]) {
482 CrossSection cs = crossSections.get(i);
483 for (Pair<CrossSection, CrossSectionLine> csl: csli.lines) {
484 if (csl.getA() == cs) {
485 if (points != null) {
486 points = csl.getB().fetchCrossSectionLinesPoints();
487 }
488 generateWaterLevels(
489 points,
490 collection);
491 break;
492 }
493 }
494 }
495
496 }
497
498 return collection;
499 }
500
501 protected Object [] createCrossSectionLineItems(
502 Map<Double, List<Pair<CrossSection, CrossSectionLine>>> km2lines
503 ) {
504 Object [] result = new Object[km2lines.size()];
505 int i = 0;
506 for (Map.Entry<Double, List<Pair<CrossSection, CrossSectionLine>>> entry:
507 km2lines.entrySet()) {
508 result[i++] = new CrossSectionLineItem(
509 entry.getKey(),
510 entry.getValue());
334 } 511 }
335 return result; 512 return result;
336 } 513 }
337 514
338 515
339 protected Object [] createCrossSectionItems() { 516 public static JFreeChart createChart(XYSeriesCollection collection) {
340 List<CrossSection> crossSections = crossSections(RIVER);
341 Object [] result = new Object[crossSections.size()];
342 for (int i = 0; i < result.length; ++i) {
343 result[i] = new CrossSectionItem(crossSections.get(i));
344 }
345 return result;
346 }
347
348 public static JFreeChart createChart(XYDataset dataset) {
349 JFreeChart chart = ChartFactory.createXYLineChart( 517 JFreeChart chart = ChartFactory.createXYLineChart(
350 null, 518 null,
351 "Abstand [m]", 519 "Abstand [m]",
352 "H\u00f6he [m]", 520 "H\u00f6he [m]",
353 dataset, 521 collection,
354 PlotOrientation.VERTICAL, 522 PlotOrientation.VERTICAL,
355 true, 523 true,
356 true, 524 true,
357 false); 525 false);
358 526

http://dive4elements.wald.intevation.org