comparison flys-artifacts/src/main/java/de/intevation/flys/artifacts/charts/CrossSectionApp.java @ 938:bd3683453928

Debugged the water fill algorithm. flys-artifacts/trunk@2330 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Thu, 14 Jul 2011 14:11:29 +0000
parents 759808931a2e
children 111794adf285
comparison
equal deleted inserted replaced
937:9e813e9137a5 938:bd3683453928
7 import java.awt.FlowLayout; 7 import java.awt.FlowLayout;
8 8
9 import javax.swing.JPanel; 9 import javax.swing.JPanel;
10 import javax.swing.JButton; 10 import javax.swing.JButton;
11 import javax.swing.JComboBox; 11 import javax.swing.JComboBox;
12 import javax.swing.JTextField;
12 import javax.swing.DefaultComboBoxModel; 13 import javax.swing.DefaultComboBoxModel;
13 14
14 import java.awt.event.ItemListener; 15 import java.awt.event.ItemListener;
15 import java.awt.event.ItemEvent; 16 import java.awt.event.ItemEvent;
16 import java.awt.event.ActionListener; 17 import java.awt.event.ActionListener;
17 import java.awt.event.ActionEvent; 18 import java.awt.event.ActionEvent;
18 19
20 import java.awt.geom.Point2D;
21 import java.awt.geom.Line2D;
22
19 import java.util.ArrayList; 23 import java.util.ArrayList;
20 import java.util.List; 24 import java.util.List;
21 import java.util.Comparator; 25 import java.util.Comparator;
22 import java.util.Collections; 26 import java.util.Collections;
27 import java.util.Iterator;
23 28
24 import java.io.File; 29 import java.io.File;
25 import java.io.IOException; 30 import java.io.IOException;
26 import java.io.FileWriter; 31 import java.io.FileWriter;
27 import java.io.PrintWriter; 32 import java.io.PrintWriter;
30 import org.jfree.ui.RefineryUtilities; 35 import org.jfree.ui.RefineryUtilities;
31 36
32 import org.jfree.chart.ChartFactory; 37 import org.jfree.chart.ChartFactory;
33 38
34 import org.jfree.chart.plot.PlotOrientation; 39 import org.jfree.chart.plot.PlotOrientation;
40 import org.jfree.chart.plot.XYPlot;
35 41
36 import org.jfree.chart.ChartUtilities; 42 import org.jfree.chart.ChartUtilities;
37 import org.jfree.chart.JFreeChart; 43 import org.jfree.chart.JFreeChart;
38 import org.jfree.chart.ChartPanel; 44 import org.jfree.chart.ChartPanel;
39 45
46 import org.jfree.chart.axis.NumberAxis;
47
40 import org.jfree.data.xy.XYDataset; 48 import org.jfree.data.xy.XYDataset;
41 import org.jfree.data.xy.DefaultXYDataset; 49 import org.jfree.data.xy.DefaultXYDataset;
42 50
43 import de.intevation.flys.model.CrossSection; 51 import de.intevation.flys.model.CrossSection;
44 import de.intevation.flys.model.CrossSectionLine; 52 import de.intevation.flys.model.CrossSectionLine;
45 import de.intevation.flys.model.CrossSectionPoint; 53 import de.intevation.flys.model.CrossSectionPoint;
46 54
55 import de.intevation.flys.geom.Lines;
56
47 import de.intevation.flys.backend.SessionFactoryProvider; 57 import de.intevation.flys.backend.SessionFactoryProvider;
48 58
49 import org.hibernate.Session; 59 import org.hibernate.Session;
50 import org.hibernate.Query; 60 import org.hibernate.Query;
51 61
62 import gnu.trove.TDoubleArrayList;
52 63
53 public class CrossSectionApp 64 public class CrossSectionApp
54 extends ApplicationFrame 65 extends ApplicationFrame
55 { 66 {
56 public static final String RIVER = System.getProperty("river", "Mosel"); 67 public static final String RIVER = System.getProperty("river", "Mosel");
57 68
58 public static final double EPSILON = 1e-4; 69 public static final double EPSILON = 1e-4;
59 70
60 public static final double TOO_SMALL = 0.2; 71 public static final double TOO_SMALL = 0.2;
61 public static final double TOO_BIG = 4000; 72 public static final double TOO_BIG = 500;
62 73
63 public static final Comparator<CrossSectionPoint> COL_POS_CMP = 74 public static final Comparator<CrossSectionPoint> COL_POS_CMP =
64 new Comparator<CrossSectionPoint>() { 75 new Comparator<CrossSectionPoint>() {
65 @Override 76 @Override
66 public int compare(CrossSectionPoint a, CrossSectionPoint b) { 77 public int compare(CrossSectionPoint a, CrossSectionPoint b) {
81 92
82 protected Session session; 93 protected Session session;
83 94
84 protected JComboBox crossSectionsCB; 95 protected JComboBox crossSectionsCB;
85 protected JComboBox crossSectionLinesCB; 96 protected JComboBox crossSectionLinesCB;
97 protected JTextField waterlevelTF;
86 98
87 protected ChartPanel chartPanel; 99 protected ChartPanel chartPanel;
100
101 protected Double lastWaterLevel;
88 102
89 103
90 public static class CrossSectionItem { 104 public static class CrossSectionItem {
91 105
92 CrossSection crossSection; 106 CrossSection crossSection;
173 }); 187 });
174 188
175 crossSectionLinesCB.addItemListener(new ItemListener() { 189 crossSectionLinesCB.addItemListener(new ItemListener() {
176 public void itemStateChanged(ItemEvent ie) { 190 public void itemStateChanged(ItemEvent ie) {
177 if (ie.getStateChange() == ItemEvent.SELECTED) { 191 if (ie.getStateChange() == ItemEvent.SELECTED) {
178 updateCrossSectionLine(((CrossSectionLineItem)ie.getItem()).line); 192 updateChart();
179 } 193 }
180 } 194 }
181 }); 195 });
182 196
183 panel.add(nav, BorderLayout.SOUTH); 197
184 198 waterlevelTF = new JTextField(5);
185 chartPanel = createChartPanel(); 199
186 200 waterlevelTF.addActionListener(new ActionListener() {
187 panel.add(chartPanel, BorderLayout.CENTER); 201 public void actionPerformed(ActionEvent ae) {
202 waterLevelChanged();
203 }
204 });
205
206 nav.add(waterlevelTF);
188 207
189 JButton dump = new JButton("dump"); 208 JButton dump = new JButton("dump");
190 209
191 dump.addActionListener(new ActionListener() { 210 dump.addActionListener(new ActionListener() {
192 public void actionPerformed(ActionEvent ae) { 211 public void actionPerformed(ActionEvent ae) {
194 } 213 }
195 }); 214 });
196 215
197 nav.add(dump); 216 nav.add(dump);
198 217
218 panel.add(nav, BorderLayout.SOUTH);
219
220 chartPanel = createChartPanel();
221
222 panel.add(chartPanel, BorderLayout.CENTER);
223
199 return panel; 224 return panel;
225 }
226
227 protected void waterLevelChanged() {
228 String value = waterlevelTF.getText();
229 try {
230 lastWaterLevel = Double.parseDouble(value);
231 }
232 catch (NumberFormatException nfe) {
233 waterlevelTF.setText(
234 lastWaterLevel != null ? lastWaterLevel.toString() : "");
235 return;
236 }
237 updateChart();
238 }
239
240 protected void updateChart() {
241
242 CrossSectionLineItem csli =
243 (CrossSectionLineItem)crossSectionLinesCB.getSelectedItem();
244
245 JFreeChart chart = createChart(csli == null
246 ? new DefaultXYDataset()
247 : generateDataset(csli.line, lastWaterLevel));
248
249 chartPanel.setChart(chart);
200 } 250 }
201 251
202 protected ChartPanel createChartPanel() { 252 protected ChartPanel createChartPanel() {
203 CrossSectionLineItem csli = 253 CrossSectionLineItem csli =
204 (CrossSectionLineItem)crossSectionLinesCB.getSelectedItem(); 254 (CrossSectionLineItem)crossSectionLinesCB.getSelectedItem();
205 255
206 if (csli == null) { 256 JFreeChart chart = createChart(csli == null
207 return new ChartPanel(null); 257 ? new DefaultXYDataset()
208 } 258 : generateDataset(csli.line, lastWaterLevel));
209
210 XYDataset dataset = crossSectionPoints(csli.line);
211
212 JFreeChart chart = createChart(dataset);
213 259
214 return new ChartPanel(chart); 260 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 } 261 }
222 262
223 protected void dumpData() { 263 protected void dumpData() {
224 264
225 CrossSectionLineItem csli = 265 CrossSectionLineItem csli =
270 out.close(); 310 out.close();
271 } 311 }
272 } 312 }
273 } 313 }
274 314
275 protected XYDataset crossSectionPoints(CrossSectionLine line) { 315 protected XYDataset generateDataset(
316 CrossSectionLine line,
317 Double waterlevel
318 ) {
276 DefaultXYDataset dataset = new DefaultXYDataset(); 319 DefaultXYDataset dataset = new DefaultXYDataset();
277 320
278 List<CrossSectionPoint> ps = line.getPoints(); 321 List<CrossSectionPoint> ps = line.getPoints();
279 322
280 List<CrossSectionPoint> points = 323 if (ps.isEmpty()) {
281 new ArrayList<CrossSectionPoint>(ps.size()); 324 return dataset;
325 }
326
327 Collections.sort(ps, COL_POS_CMP);
328
329 List<Point2D> points = new ArrayList<Point2D>(ps.size());
282 330
283 for (CrossSectionPoint p: ps) { 331 for (CrossSectionPoint p: ps) {
284 if (isValid(p.getX().doubleValue()) 332 double x = p.getX().doubleValue();
285 && isValid(p.getY().doubleValue())) { 333 double y = p.getY().doubleValue();
286 points.add(p); 334 if (isValid(x) && isValid(y)) {
335 points.add(new Point2D.Double(x, y));
287 } 336 }
288 } 337 }
289 338
290 if (points.isEmpty()) { 339 if (points.isEmpty()) {
291 return dataset; 340 return dataset;
292 } 341 }
293 342
294 Collections.sort(points, COL_POS_CMP);
295
296 double [] xs = new double[points.size()]; 343 double [] xs = new double[points.size()];
297 double [] ys = new double[xs.length]; 344 double [] ys = new double[xs.length];
298 345
299 double x = points.get(0).getX().doubleValue(); 346 xs[0] = points.get(0).getX();
300 double y = points.get(0).getY().doubleValue(); 347 ys[0] = points.get(0).getY();
301
302 xs[0] = x;
303 ys[0] = y;
304 348
305 for (int i = 1; i < xs.length; ++i) { 349 for (int i = 1; i < xs.length; ++i) {
306 CrossSectionPoint p = points.get(i); 350 Point2D p = points.get(i);
307 x = p.getX().doubleValue(); 351 double x = p.getX();
308 y = p.getY().doubleValue(); 352 double y = p.getY();
309 353
310 if (x <= xs[i-1]) { 354 if (x <= xs[i-1]) {
311 x = xs[i-1] + EPSILON; 355 x = xs[i-1] + EPSILON;
312 } 356 }
313 xs[i] = x; 357 xs[i] = x;
314 ys[i] = y; 358 ys[i] = y;
315 } 359 }
316 360
361 if (waterlevel != null) {
362 double [][] data = createWaterLines(points, waterlevel);
363 dataset.addSeries(String.valueOf(waterlevel), data);
364 }
365
317 CrossSection cs = line.getCrossSection(); 366 CrossSection cs = line.getCrossSection();
318 367
319 String legend = (cs != null ? cs.getDescription() : "???") 368 String legend = (cs != null ? cs.getDescription() : "???")
320 + " " + Math.round(line.getKm().doubleValue() * 1000d)/1000d; 369 + " " + Math.round(line.getKm().doubleValue() * 1000d)/1000d;
321 370
322 dataset.addSeries(legend, new double [][] { xs, ys }); 371 dataset.addSeries(legend, new double [][] { xs, ys });
323 372
324 return dataset; 373 return dataset;
374 }
375
376 protected static double [][] createWaterLines(
377 List<Point2D> points,
378 double waterlevel
379 ) {
380 List<Line2D> lines = Lines.fillWater(points, waterlevel);
381
382 TDoubleArrayList lxs = new TDoubleArrayList();
383 TDoubleArrayList lys = new TDoubleArrayList();
384
385 for (Iterator<Line2D> iter = lines.iterator(); iter.hasNext();) {
386 Line2D l = iter.next();
387 Point2D p1 = l.getP1();
388 Point2D p2 = l.getP2();
389 lxs.add(p1.getX());
390 lys.add(p1.getY());
391 lxs.add(p2.getX());
392 lys.add(p2.getY());
393 if (iter.hasNext()) {
394 lxs.add(Double.NaN);
395 lys.add(Double.NaN);
396 }
397 }
398
399 return new double [][] { lxs.toNativeArray(), lys.toNativeArray() };
325 } 400 }
326 401
327 protected void updateCrossSection(CrossSection crossSection) { 402 protected void updateCrossSection(CrossSection crossSection) {
328 Object [] cslis = createCrossSectionLineItems(crossSection); 403 Object [] cslis = createCrossSectionLineItems(crossSection);
329 DefaultComboBoxModel dcbm = new DefaultComboBoxModel(cslis); 404 DefaultComboBoxModel dcbm = new DefaultComboBoxModel(cslis);
332 } 407 }
333 crossSectionLinesCB.setModel(dcbm); 408 crossSectionLinesCB.setModel(dcbm);
334 if (cslis.length > 0) { 409 if (cslis.length > 0) {
335 CrossSectionLine line = 410 CrossSectionLine line =
336 ((CrossSectionLineItem)cslis[0]).line; 411 ((CrossSectionLineItem)cslis[0]).line;
337 updateCrossSectionLine(line); 412 }
338 } 413 updateChart();
339 } 414 }
340 415
341 protected Object [] createCrossSectionLineItems(CrossSection cs) { 416 protected Object [] createCrossSectionLineItems(CrossSection cs) {
342 List<CrossSectionLine> lines = cs.getLines(); 417 List<CrossSectionLine> lines = cs.getLines();
343 Object [] result = new Object[lines.size()]; 418 Object [] result = new Object[lines.size()];
365 dataset, 440 dataset,
366 PlotOrientation.VERTICAL, 441 PlotOrientation.VERTICAL,
367 true, 442 true,
368 true, 443 true,
369 false); 444 false);
445
446 XYPlot plot = chart.getXYPlot();
447 NumberAxis yAxis = (NumberAxis)plot.getRangeAxis();
448 yAxis.setAutoRangeIncludesZero(false);
449
370 ChartUtilities.applyCurrentTheme(chart); 450 ChartUtilities.applyCurrentTheme(chart);
371 return chart; 451 return chart;
372 } 452 }
373 453
374 public static void main(String [] args) { 454 public static void main(String [] args) {

http://dive4elements.wald.intevation.org