From 93d640de65a1ecedfef89c96521c21632f96f372 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 2 Jan 2013 11:22:11 -0800 Subject: micropoint: Add MicroDataPoint This holds height/speed/accel data all in one place Signed-off-by: Keith Packard --- micropeak/MicroDataPoint.java | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 micropeak/MicroDataPoint.java (limited to 'micropeak/MicroDataPoint.java') diff --git a/micropeak/MicroDataPoint.java b/micropeak/MicroDataPoint.java new file mode 100644 index 00000000..3fd1e641 --- /dev/null +++ b/micropeak/MicroDataPoint.java @@ -0,0 +1,39 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.micropeak; + +public class MicroDataPoint { + public double time; + public double height; + public double speed; + public double accel; + + public MicroDataPoint (double height, double speed, double accel, double time) { + this.height = height; + this.speed = speed; + this.accel = accel; + this.time = time; + } + + public MicroDataPoint(MicroData data, int i) { + this(data.height(i), + data.speed(i), + data.acceleration(i), + data.time(i)); + } +} \ No newline at end of file -- cgit v1.2.3 From 2c423d9287c6b9ea7233f5e3430682cb1c865da1 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 2 Jan 2013 11:44:32 -0800 Subject: micropeak: Add CSV export Signed-off-by: Keith Packard --- micropeak/Makefile.am | 1 + micropeak/MicroData.java | 4 ++ micropeak/MicroDataPoint.java | 7 ++- micropeak/MicroExport.java | 106 ++++++++++++++++++++++++++++++++++++++++++ micropeak/MicroPeak.java | 22 ++++++++- 5 files changed, 136 insertions(+), 4 deletions(-) create mode 100644 micropeak/MicroExport.java (limited to 'micropeak/MicroDataPoint.java') diff --git a/micropeak/Makefile.am b/micropeak/Makefile.am index 26431bd5..f5f8ccd9 100644 --- a/micropeak/Makefile.am +++ b/micropeak/Makefile.am @@ -12,6 +12,7 @@ micropeak_JAVA= \ MicroData.java \ MicroDataPoint.java \ MicroDownload.java \ + MicroExport.java \ MicroFrame.java \ MicroGraph.java \ MicroSave.java \ diff --git a/micropeak/MicroData.java b/micropeak/MicroData.java index 2afd3cd7..836d3c35 100644 --- a/micropeak/MicroData.java +++ b/micropeak/MicroData.java @@ -221,6 +221,10 @@ public class MicroData { return alt; } + public double pressure(int i) { + return pressures[i]; + } + public double height(int i) { return altitude(i) - ground_altitude; } diff --git a/micropeak/MicroDataPoint.java b/micropeak/MicroDataPoint.java index 3fd1e641..c58708e6 100644 --- a/micropeak/MicroDataPoint.java +++ b/micropeak/MicroDataPoint.java @@ -19,11 +19,13 @@ package org.altusmetrum.micropeak; public class MicroDataPoint { public double time; + public double pressure; public double height; public double speed; public double accel; - public MicroDataPoint (double height, double speed, double accel, double time) { + public MicroDataPoint (double pressure, double height, double speed, double accel, double time) { + this.pressure = pressure; this.height = height; this.speed = speed; this.accel = accel; @@ -31,7 +33,8 @@ public class MicroDataPoint { } public MicroDataPoint(MicroData data, int i) { - this(data.height(i), + this(data.pressure(i), + data.height(i), data.speed(i), data.acceleration(i), data.time(i)); diff --git a/micropeak/MicroExport.java b/micropeak/MicroExport.java new file mode 100644 index 00000000..06a03469 --- /dev/null +++ b/micropeak/MicroExport.java @@ -0,0 +1,106 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.micropeak; + +import java.io.*; +import java.util.ArrayList; + +import java.awt.*; +import javax.swing.*; +import javax.swing.filechooser.FileNameExtensionFilter; +import org.altusmetrum.AltosLib.*; +import org.altusmetrum.altosuilib.*; + +public class MicroExport extends JFileChooser { + + JFrame frame; + MicroData data; + + public boolean runDialog() { + int ret; + + setSelectedFile(new File(AltosLib.replace_extension(data.name, ".csv"))); + for (;;) { + ret = showSaveDialog(frame); + if (ret != APPROVE_OPTION) + return false; + File file; + String filename; + file = getSelectedFile(); + if (file == null) + continue; + if (!file.getName().contains(".")) { + String fullname = file.getPath(); + file = new File(fullname.concat(".csv")); + } + filename = file.getName(); + if (file.exists()) { + if (file.isDirectory()) { + JOptionPane.showMessageDialog(frame, + String.format("\"%s\" is a directory", + filename), + "Directory", + JOptionPane.ERROR_MESSAGE); + continue; + } + int r = JOptionPane.showConfirmDialog(frame, + String.format("\"%s\" already exists. Overwrite?", + filename), + "Overwrite file?", + JOptionPane.YES_NO_OPTION); + if (r != JOptionPane.YES_OPTION) + continue; + + if (!file.canWrite()) { + JOptionPane.showMessageDialog(frame, + String.format("\"%s\" is not writable", + filename), + "File not writable", + JOptionPane.ERROR_MESSAGE); + continue; + } + } + try { + FileWriter fw = new FileWriter(file); + PrintWriter pw = new PrintWriter(fw); + pw.printf(" Time, Press, Height, Speed, Accel\n"); + for (MicroDataPoint point : data.points()) { + pw.printf("%5.2f,%6.0f,%7.1f,%7.2f,%7.2f\n", + point.time, point.pressure, point.height, point.speed, point.accel); + } + fw.close(); + return true; + } catch (FileNotFoundException fe) { + JOptionPane.showMessageDialog(frame, + fe.getMessage(), + "Cannot create file", + JOptionPane.ERROR_MESSAGE); + } catch (IOException ioe) { + } + } + } + + public MicroExport(JFrame frame, MicroData data) { + this.frame = frame; + this.data = data; + setDialogTitle("Export MicroPeak Data File"); + setFileFilter(new FileNameExtensionFilter("MicroPeak CSV file", + "csv")); + setCurrentDirectory(AltosUIPreferences.logdir()); + } +} diff --git a/micropeak/MicroPeak.java b/micropeak/MicroPeak.java index 544f3ae0..f2f09a10 100644 --- a/micropeak/MicroPeak.java +++ b/micropeak/MicroPeak.java @@ -101,12 +101,15 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene new MicroDownload(this, device); } - private void Save() { - if (data == null) { + private void no_data() { JOptionPane.showMessageDialog(this, "No data available", "No data", JOptionPane.INFORMATION_MESSAGE); + } + private void Save() { + if (data == null) { + no_data(); return; } MicroSave save = new MicroSave (this, data); @@ -114,6 +117,15 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene SetName(data.name); } + private void Export() { + if (data == null) { + no_data(); + return; + } + MicroExport export = new MicroExport (this, data); + export.runDialog(); + } + private void Close() { setVisible(false); dispose(); @@ -131,6 +143,8 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene SelectFile(); else if ("Download".equals(ev.getActionCommand())) DownloadData(); + else if ("Export".equals(ev.getActionCommand())) + Export(); else if ("Preferences".equals(ev.getActionCommand())) Preferences(); else if ("Save a Copy".equals(ev.getActionCommand())) @@ -169,6 +183,10 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene fileMenu.add(saveAction); saveAction.addActionListener(this); + JMenuItem exportAction = new JMenuItem("Export"); + fileMenu.add(exportAction); + exportAction.addActionListener(this); + JMenuItem preferencesAction = new JMenuItem("Preferences"); fileMenu.add(preferencesAction); preferencesAction.addActionListener(this); -- cgit v1.2.3 From ab9caa22ea905844a99e08b5f6d3b072f094283e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 9 Feb 2013 01:59:18 -0800 Subject: micropeak: Use altosuilib graphing functions Move these out of micropeak and into shared code Signed-off-by: Keith Packard --- micropeak/MicroData.java | 45 ++++++++++++- micropeak/MicroDataPoint.java | 25 +++++++- micropeak/MicroGraph.java | 142 +++--------------------------------------- micropeak/MicroPeak.java | 7 ++- 4 files changed, 79 insertions(+), 140 deletions(-) (limited to 'micropeak/MicroDataPoint.java') diff --git a/micropeak/MicroData.java b/micropeak/MicroData.java index 473af44b..26e3c07d 100644 --- a/micropeak/MicroData.java +++ b/micropeak/MicroData.java @@ -21,6 +21,7 @@ import java.lang.*; import java.io.*; import java.util.*; import org.altusmetrum.altoslib_1.*; +import org.altusmetrum.altosuilib_1.*; class MicroIterator implements Iterator { int i; @@ -56,7 +57,40 @@ class MicroIterable implements Iterable { } } -public class MicroData { +class MicroUIIterator implements Iterator { + int i; + MicroData data; + + public boolean hasNext() { + return i < data.pressures.length; + } + + public AltosUIDataPoint next() { + return new MicroDataPoint(data, i++); + } + + public MicroUIIterator (MicroData data) { + this.data = data; + i = 0; + } + + public void remove() { + } +} + +class MicroUIIterable implements Iterable { + MicroData data; + + public Iterator iterator() { + return new MicroUIIterator(data); + } + + public MicroUIIterable(MicroData data) { + this.data = data; + } +} + +public class MicroData implements AltosUIDataSet { public int ground_pressure; public int min_pressure; public int[] pressures; @@ -65,7 +99,6 @@ public class MicroData { private ArrayList bytes; String name; - class FileEndedException extends Exception { } @@ -178,6 +211,14 @@ public class MicroData { return AltosConvert.pressure_to_altitude(pressures[i]); } + public String name() { + return name; + } + + public Iterable dataPoints() { + return new MicroUIIterable(this); + } + public Iterable points() { return new MicroIterable(this); } diff --git a/micropeak/MicroDataPoint.java b/micropeak/MicroDataPoint.java index c58708e6..a81eb0d3 100644 --- a/micropeak/MicroDataPoint.java +++ b/micropeak/MicroDataPoint.java @@ -17,13 +17,36 @@ package org.altusmetrum.micropeak; -public class MicroDataPoint { +import org.altusmetrum.altosuilib_1.*; + +public class MicroDataPoint implements AltosUIDataPoint { public double time; public double pressure; public double height; public double speed; public double accel; + public static final int data_height = 0; + public static final int data_speed = 1; + public static final int data_accel = 2; + + public double x() { + return time; + } + + public double y(int index) { + switch (index) { + case data_height: + return height; + case data_speed: + return speed; + case data_accel: + return accel; + default: + return 0; + } + } + public MicroDataPoint (double pressure, double height, double speed, double accel, double time) { this.pressure = pressure; this.height = height; diff --git a/micropeak/MicroGraph.java b/micropeak/MicroGraph.java index e8a6ea16..0071a160 100644 --- a/micropeak/MicroGraph.java +++ b/micropeak/MicroGraph.java @@ -23,6 +23,7 @@ import java.util.ArrayList; import java.awt.*; import javax.swing.*; import org.altusmetrum.altoslib_1.*; +import org.altusmetrum.altosuilib_1.*; import org.jfree.ui.*; import org.jfree.chart.*; @@ -34,146 +35,17 @@ import org.jfree.chart.labels.*; import org.jfree.data.xy.*; import org.jfree.data.*; -class MicroSeries extends XYSeries { - NumberAxis axis; - String label; - String units; - Color color; - XYItemRenderer renderer; - - void set_units(String units) { - this.units = units; - - axis.setLabel(String.format("%s (%s)", label, units)); - - StandardXYToolTipGenerator ttg; - - ttg = new StandardXYToolTipGenerator(String.format("{1}s: {2}%s ({0})", units), - new java.text.DecimalFormat("0.00"), - new java.text.DecimalFormat("0.00")); - renderer.setBaseToolTipGenerator(ttg); - } - - void set_enable(boolean enable) { - renderer.setSeriesVisible(0, enable); - axis.setVisible(enable); - } - - public MicroSeries (String label, String units, Color color) { - super(label); - this.label = label; - this.units = units; - this.color = color; - - axis = new NumberAxis(); - axis.setLabelPaint(color); - axis.setTickLabelPaint(color); - - renderer = new XYLineAndShapeRenderer(true, false); - renderer.setSeriesPaint(0, color); - set_units(units); - } -} - -public class MicroGraph implements AltosUnitsListener { - - XYPlot plot; - JFreeChart chart; - ChartPanel panel; - NumberAxis xAxis; - MicroSeries heightSeries; - MicroSeries speedSeries; - MicroSeries accelSeries; +public class MicroGraph extends AltosUIGraph { static final private Color height_color = new Color(194,31,31); static final private Color speed_color = new Color(31,194,31); static final private Color accel_color = new Color(31,31,194); - static final private Color gridline_color = new Color(0, 0, 0); - static final private Color border_color = new Color(255, 255, 255); - static final private Color background_color = new Color(255, 255, 255); - - MicroData data; - - public JPanel panel() { - return panel; - } - - private MicroSeries addSeries(int index, String label, String units, Color color) { - MicroSeries series = new MicroSeries(label, units, color); - XYSeriesCollection dataset = new XYSeriesCollection(series); - - series.renderer.setPlot(plot); - plot.setRangeAxis(index, series.axis); - plot.setDataset(index, dataset); - plot.setRenderer(index, series.renderer); - plot.mapDatasetToRangeAxis(index, index); - return series; - } - - public void resetData() { - heightSeries.clear(); - speedSeries.clear(); - accelSeries.clear(); - if (data != null) { - for (MicroDataPoint point : data.points()) { - heightSeries.add(point.time, AltosConvert.height.value(point.height)); - speedSeries.add(point.time, AltosConvert.speed.value(point.speed)); - accelSeries.add(point.time, AltosConvert.accel.value(point.accel)); - } - } -// accelSeries.set_enable(false); - } - - public void setName (String name) { - chart.setTitle(name); - } - - public void setData (MicroData data) { - this.data = data; - if (data != null) - setName(data.name); - resetData(); - } - - public void units_changed(boolean imperial_units) { - heightSeries.set_units(AltosConvert.height.show_units()); - speedSeries.set_units(AltosConvert.speed.show_units()); - accelSeries.set_units(AltosConvert.accel.show_units()); - resetData(); - } - - public MicroGraph() { - - xAxis = new NumberAxis("Time (s)"); - - xAxis.setAutoRangeIncludesZero(true); - - plot = new XYPlot(); - plot.setDomainAxis(xAxis); - plot.setOrientation(PlotOrientation.VERTICAL); - plot.setDomainPannable(true); - plot.setRangePannable(true); - - chart = new JFreeChart("Flight", JFreeChart.DEFAULT_TITLE_FONT, - plot, true); - - ChartUtilities.applyCurrentTheme(chart); - - heightSeries = addSeries(0, "Height", AltosConvert.height.show_units(), height_color); - speedSeries = addSeries(1, "Speed", AltosConvert.speed.show_units(), speed_color); - accelSeries = addSeries(2, "Acceleration", AltosConvert.accel.show_units(), accel_color); - - plot.setDomainGridlinePaint(gridline_color); - plot.setRangeGridlinePaint(gridline_color); - plot.setBackgroundPaint(background_color); - plot.setBackgroundAlpha((float) 1); - chart.setBackgroundPaint(background_color); - chart.setBorderPaint(border_color); - panel = new ChartPanel(chart); - panel.setMouseWheelEnabled(true); - panel.setPreferredSize(new java.awt.Dimension(800, 500)); + public MicroGraph(AltosUIEnable enable) { + super(enable); - AltosPreferences.register_units_listener(this); + addSeries(0, "Height", MicroDataPoint.data_height, AltosConvert.height, height_color); + addSeries(1, "Speed", MicroDataPoint.data_speed, AltosConvert.speed, speed_color); + addSeries(2, "Acceleration", MicroDataPoint.data_accel, AltosConvert.accel, accel_color); } } \ No newline at end of file diff --git a/micropeak/MicroPeak.java b/micropeak/MicroPeak.java index 63387ed1..871d5cc3 100644 --- a/micropeak/MicroPeak.java +++ b/micropeak/MicroPeak.java @@ -30,6 +30,7 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene File filename; MicroGraph graph; + AltosUIEnable enable; MicroStatsTable stats; MicroRaw raw; MicroData data; @@ -44,7 +45,7 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene return mp.SetData(data); } this.data = data; - graph.setData(data); + graph.setDataSet(data); stats.setData(data); raw.setData(data); setTitle(data.name); @@ -236,10 +237,12 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene } }); - graph = new MicroGraph(); + enable = new AltosUIEnable(); + graph = new MicroGraph(enable); stats = new MicroStatsTable(); raw = new MicroRaw(); pane.add(graph.panel, "Graph"); + pane.add(enable, "Configure Graph"); pane.add(stats, "Statistics"); JScrollPane scroll = new JScrollPane(raw); pane.add(scroll, "Raw Data"); -- cgit v1.2.3 From 0169e56ad030c0096b1068d00f06957990dfb31f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 9 Feb 2013 20:24:33 -0800 Subject: altosuilib/micropeak: Add state markers to micropeak graph I think this makes the micropeak graph as functional as the altosui graph Signed-off-by: Keith Packard --- altosuilib/AltosUIDataPoint.java | 4 +- altosuilib/AltosUIEnable.java | 14 +++--- altosuilib/AltosUIGraph.java | 30 ++++++++---- altosuilib/AltosUIGrapher.java | 46 +++++++++++++++++ altosuilib/AltosUIMarker.java | 103 +++++++++++++++++++++++++++++++++++++++ altosuilib/AltosUISeries.java | 48 +++++++++++------- altosuilib/Makefile.am | 3 ++ micropeak/MicroData.java | 2 + micropeak/MicroDataPoint.java | 31 +++++++++--- micropeak/MicroGraph.java | 8 +-- micropeak/MicroPeak.java | 12 +++-- micropeak/MicroStats.java | 37 ++++++++++++++ micropeak/MicroStatsTable.java | 4 -- 13 files changed, 287 insertions(+), 55 deletions(-) create mode 100644 altosuilib/AltosUIGrapher.java create mode 100644 altosuilib/AltosUIMarker.java (limited to 'micropeak/MicroDataPoint.java') diff --git a/altosuilib/AltosUIDataPoint.java b/altosuilib/AltosUIDataPoint.java index 38857fd1..a98f7cdb 100644 --- a/altosuilib/AltosUIDataPoint.java +++ b/altosuilib/AltosUIDataPoint.java @@ -20,4 +20,6 @@ package org.altusmetrum.altosuilib_1; public interface AltosUIDataPoint { public abstract double x(); public abstract double y(int index); -} \ No newline at end of file + public abstract int id(int index); + public abstract String id_name(int index); +} diff --git a/altosuilib/AltosUIEnable.java b/altosuilib/AltosUIEnable.java index e5695fa0..297cf320 100644 --- a/altosuilib/AltosUIEnable.java +++ b/altosuilib/AltosUIEnable.java @@ -41,28 +41,28 @@ public class AltosUIEnable extends Container { int y; class GraphElement implements ActionListener { - AltosUISeries series; + AltosUIGrapher grapher; JLabel label; JRadioButton enable; String name; public void actionPerformed(ActionEvent ae) { - series.set_enable(enable.isSelected()); + grapher.set_enable(enable.isSelected()); } - GraphElement (String name, AltosUISeries series, boolean enabled) { + GraphElement (String name, AltosUIGrapher grapher, boolean enabled) { this.name = name; - this.series = series; + this.grapher = grapher; label = new JLabel(name); enable = new JRadioButton("Enable", enabled); - series.set_enable(enabled); + grapher.set_enable(enabled); enable.addActionListener(this); } } - public void add(String name, AltosUISeries series, boolean enabled) { + public void add(String name, AltosUIGrapher grapher, boolean enabled) { - GraphElement e = new GraphElement(name, series, enabled); + GraphElement e = new GraphElement(name, grapher, enabled); /* Add label */ GridBagConstraints c = new GridBagConstraints(); diff --git a/altosuilib/AltosUIGraph.java b/altosuilib/AltosUIGraph.java index e79e36ba..e212093a 100644 --- a/altosuilib/AltosUIGraph.java +++ b/altosuilib/AltosUIGraph.java @@ -41,8 +41,9 @@ public class AltosUIGraph implements AltosUnitsListener { public ChartPanel panel; NumberAxis xAxis; AltosUIEnable enable; - ArrayList series; + ArrayList graphers; AltosUIDataSet dataSet; + int index; static final private Color gridline_color = new Color(0, 0, 0); static final private Color border_color = new Color(255, 255, 255); @@ -52,7 +53,7 @@ public class AltosUIGraph implements AltosUnitsListener { return panel; } - public void addSeries(int index, String label, int fetch, AltosUnits units, Color color) { + public void addSeries(String label, int fetch, AltosUnits units, Color color) { AltosUISeries series = new AltosUISeries(label, fetch, units, color); XYSeriesCollection dataset = new XYSeriesCollection(series); @@ -63,22 +64,30 @@ public class AltosUIGraph implements AltosUnitsListener { plot.mapDatasetToRangeAxis(index, index); if (enable != null) enable.add(label, series, true); - this.series.add(series); + this.graphers.add(series); + index++; } + public void addMarker(String label, int fetch, Color color) { + AltosUIMarker marker = new AltosUIMarker(fetch, color, plot); + if (enable != null) + enable.add(label, marker, true); + this.graphers.add(marker); + } + public void resetData() { - for (AltosUISeries s : series) - s.clear(); + for (AltosUIGrapher g : graphers) + g.clear(); if (dataSet != null) { for (AltosUIDataPoint dataPoint : dataSet.dataPoints()) - for (AltosUISeries s : series) - s.add(dataPoint); + for (AltosUIGrapher g : graphers) + g.add(dataPoint); } } public void units_changed(boolean imperial_units) { - for (AltosUISeries s : series) - s.set_units(); + for (AltosUIGrapher g : graphers) + g.set_units(); resetData(); } @@ -96,7 +105,8 @@ public class AltosUIGraph implements AltosUnitsListener { public AltosUIGraph(AltosUIEnable enable) { this.enable = enable; - this.series = new ArrayList(); + this.graphers = new ArrayList(); + this.index = 0; xAxis = new NumberAxis("Time (s)"); diff --git a/altosuilib/AltosUIGrapher.java b/altosuilib/AltosUIGrapher.java new file mode 100644 index 00000000..c627fec5 --- /dev/null +++ b/altosuilib/AltosUIGrapher.java @@ -0,0 +1,46 @@ +/* + * Copyright © 2013 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altosuilib_1; + +import java.io.*; +import java.util.ArrayList; + +import java.awt.*; +import javax.swing.*; +import org.altusmetrum.altoslib_1.*; + +import org.jfree.ui.*; +import org.jfree.chart.*; +import org.jfree.chart.plot.*; +import org.jfree.chart.axis.*; +import org.jfree.chart.renderer.*; +import org.jfree.chart.renderer.xy.*; +import org.jfree.chart.labels.*; +import org.jfree.data.xy.*; +import org.jfree.data.*; + +interface AltosUIGrapher { + + public abstract void set_units(); + + public abstract void clear(); + + public abstract void add(AltosUIDataPoint dataPoint); + + public abstract void set_enable(boolean enable); +} diff --git a/altosuilib/AltosUIMarker.java b/altosuilib/AltosUIMarker.java new file mode 100644 index 00000000..560153f2 --- /dev/null +++ b/altosuilib/AltosUIMarker.java @@ -0,0 +1,103 @@ +/* + * Copyright © 2013 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altosuilib_1; + +import java.io.*; +import java.util.ArrayList; + +import java.awt.*; +import javax.swing.*; +import org.altusmetrum.altoslib_1.*; + +import org.jfree.ui.*; +import org.jfree.chart.*; +import org.jfree.chart.plot.*; +import org.jfree.chart.axis.*; +import org.jfree.chart.renderer.*; +import org.jfree.chart.renderer.xy.*; +import org.jfree.chart.labels.*; +import org.jfree.data.xy.*; +import org.jfree.data.*; + +public class AltosUIMarker implements AltosUIGrapher { + ArrayList markers; + int last_id; + XYPlot plot; + boolean enabled; + int fetch; + Color color; + + private void remove_markers() { + for (ValueMarker marker : markers) + plot.removeDomainMarker(marker); + } + + private void add_markers() { + for (ValueMarker marker : markers) + plot.addDomainMarker(marker); + } + + public void set_units() { + } + + public void set_enable(boolean enable) { + if (enabled == enable) + return; + if (enable) + add_markers(); + else + remove_markers(); + enabled = enable; + } + + public void clear() { + if (enabled) + remove_markers(); + markers = new ArrayList(); + } + + public void add(AltosUIDataPoint dataPoint) { + int id = dataPoint.id(fetch); + if (id < 0) + return; + if (id == last_id) + return; + ValueMarker marker = new ValueMarker(dataPoint.x()); + marker.setLabel(dataPoint.id_name(fetch)); + marker.setLabelAnchor(RectangleAnchor.TOP_RIGHT); + marker.setLabelTextAnchor(TextAnchor.TOP_LEFT); + marker.setPaint(color); + if (enabled) + plot.addDomainMarker(marker); + markers.add(marker); + last_id = id; + } + + public AltosUIMarker (int fetch, Color color, XYPlot plot, boolean enable) { + markers = new ArrayList(); + last_id = -1; + this.fetch = fetch; + this.color = color; + this.plot = plot; + this.enabled = enable; + } + + public AltosUIMarker (int fetch, Color color, XYPlot plot) { + this(fetch, color, plot, true); + } +} \ No newline at end of file diff --git a/altosuilib/AltosUISeries.java b/altosuilib/AltosUISeries.java index ea76e741..26679471 100644 --- a/altosuilib/AltosUISeries.java +++ b/altosuilib/AltosUISeries.java @@ -34,54 +34,66 @@ import org.jfree.chart.labels.*; import org.jfree.data.xy.*; import org.jfree.data.*; -public class AltosUISeries extends XYSeries { - NumberAxis axis; +public class AltosUISeries extends XYSeries implements AltosUIGrapher { + AltosUIAxis axis; String label; AltosUnits units; Color color; XYItemRenderer renderer; int fetch; + boolean enable; - void set_units() { - String units_string = units.show_units(); - axis.setLabel(String.format("%s (%s)", label, units_string)); - + public void set_units() { + axis.set_units(); StandardXYToolTipGenerator ttg; String example = units.graph_format(4); - ttg = new StandardXYToolTipGenerator(String.format("{1}s: {2}%s ({0})", units_string), + ttg = new StandardXYToolTipGenerator(String.format("{1}s: {2}%s ({0})", + units.show_units()), new java.text.DecimalFormat(example), new java.text.DecimalFormat(example)); renderer.setBaseToolTipGenerator(ttg); } - void set_enable(boolean enable) { - renderer.setSeriesVisible(0, enable); - axis.setVisible(enable); + public void set_enable(boolean enable) { + if (this.enable != enable) { + this.enable = enable; + renderer.setSeriesVisible(0, enable); + axis.set_enable(enable); + } } public void add(AltosUIDataPoint dataPoint) { super.add(dataPoint.x(), dataPoint.y(fetch)); } - public void set_axis(NumberAxis axis) { - this.axis = axis; - } - - public AltosUISeries (String label, int fetch, AltosUnits units, Color color) { + public AltosUISeries (String label, int fetch, AltosUnits units, Color color, + boolean enable, AltosUIAxis axis) { super(label); this.label = label; this.fetch = fetch; this.units = units; this.color = color; + this.enable = enable; + this.axis = axis; - axis = new NumberAxis(); - axis.setLabelPaint(color); - axis.setTickLabelPaint(color); + axis.ref(this.enable); renderer = new XYLineAndShapeRenderer(true, false); renderer.setSeriesPaint(0, color); set_units(); } + + public AltosUISeries (String label, int fetch, AltosUnits units, Color color, boolean enable) { + this(label, fetch, units, color, + enable, + new AltosUIAxis(label, units, color)); + } + + public AltosUISeries (String label, int fetch, AltosUnits units, Color color) { + this(label, fetch, units, color, + true, + new AltosUIAxis(label, units, color)); + } } diff --git a/altosuilib/Makefile.am b/altosuilib/Makefile.am index e338b7cd..faf7921f 100644 --- a/altosuilib/Makefile.am +++ b/altosuilib/Makefile.am @@ -14,14 +14,17 @@ altosuilib_JAVA = \ AltosFontListener.java \ AltosPositionListener.java \ AltosUIConfigure.java \ + AltosUIAxis.java \ AltosUIDataPoint.java \ AltosUIDataSet.java \ AltosUIGraph.java \ + AltosUIGrapher.java \ AltosUIDialog.java \ AltosUIEnable.java \ AltosUIFrame.java \ AltosUILib.java \ AltosUIListener.java \ + AltosUIMarker.java \ AltosUIPreferencesBackend.java \ AltosUIPreferences.java \ AltosUISeries.java \ diff --git a/micropeak/MicroData.java b/micropeak/MicroData.java index 26e3c07d..4c0ed4c3 100644 --- a/micropeak/MicroData.java +++ b/micropeak/MicroData.java @@ -98,6 +98,7 @@ public class MicroData implements AltosUIDataSet { private double ground_altitude; private ArrayList bytes; String name; + MicroStats stats; class FileEndedException extends Exception { } @@ -380,6 +381,7 @@ public class MicroData implements AltosUIDataSet { crc_valid = crc == current_crc; time_step = 0.192; + stats = new MicroStats(this); } catch (FileEndedException fe) { throw new IOException("File Ended Unexpectedly"); } catch (NonHexcharException ne) { diff --git a/micropeak/MicroDataPoint.java b/micropeak/MicroDataPoint.java index a81eb0d3..61faf794 100644 --- a/micropeak/MicroDataPoint.java +++ b/micropeak/MicroDataPoint.java @@ -20,15 +20,17 @@ package org.altusmetrum.micropeak; import org.altusmetrum.altosuilib_1.*; public class MicroDataPoint implements AltosUIDataPoint { - public double time; - public double pressure; - public double height; - public double speed; - public double accel; + public double time; + public double pressure; + public double height; + public double speed; + public double accel; + public MicroStats stats; public static final int data_height = 0; public static final int data_speed = 1; public static final int data_accel = 2; + public static final int data_state = 3; public double x() { return time; @@ -47,12 +49,26 @@ public class MicroDataPoint implements AltosUIDataPoint { } } - public MicroDataPoint (double pressure, double height, double speed, double accel, double time) { + public int id(int index) { + if (index == data_state) { + return stats.state(time); + } + return 0; + } + + public String id_name(int index) { + if (index == data_state) + return stats.state_name(time); + return ""; + } + + public MicroDataPoint (double pressure, double height, double speed, double accel, double time, MicroStats stats) { this.pressure = pressure; this.height = height; this.speed = speed; this.accel = accel; this.time = time; + this.stats = stats; } public MicroDataPoint(MicroData data, int i) { @@ -60,6 +76,7 @@ public class MicroDataPoint implements AltosUIDataPoint { data.height(i), data.speed(i), data.acceleration(i), - data.time(i)); + data.time(i), + data.stats); } } \ No newline at end of file diff --git a/micropeak/MicroGraph.java b/micropeak/MicroGraph.java index 0071a160..50508a61 100644 --- a/micropeak/MicroGraph.java +++ b/micropeak/MicroGraph.java @@ -40,12 +40,14 @@ public class MicroGraph extends AltosUIGraph { static final private Color height_color = new Color(194,31,31); static final private Color speed_color = new Color(31,194,31); static final private Color accel_color = new Color(31,31,194); + static final private Color state_color = new Color(3,3,3); public MicroGraph(AltosUIEnable enable) { super(enable); - addSeries(0, "Height", MicroDataPoint.data_height, AltosConvert.height, height_color); - addSeries(1, "Speed", MicroDataPoint.data_speed, AltosConvert.speed, speed_color); - addSeries(2, "Acceleration", MicroDataPoint.data_accel, AltosConvert.accel, accel_color); + addSeries("Height", MicroDataPoint.data_height, AltosConvert.height, height_color); + addSeries("Speed", MicroDataPoint.data_speed, AltosConvert.speed, speed_color); + addSeries("Acceleration", MicroDataPoint.data_accel, AltosConvert.accel, accel_color); + addMarker("State", MicroDataPoint.data_state, state_color); } } \ No newline at end of file diff --git a/micropeak/MicroPeak.java b/micropeak/MicroPeak.java index 871d5cc3..57f17dbe 100644 --- a/micropeak/MicroPeak.java +++ b/micropeak/MicroPeak.java @@ -31,9 +31,10 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene File filename; MicroGraph graph; AltosUIEnable enable; - MicroStatsTable stats; + MicroStatsTable statsTable; MicroRaw raw; MicroData data; + MicroStats stats; Container container; JTabbedPane pane; static int number_of_windows; @@ -45,8 +46,9 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene return mp.SetData(data); } this.data = data; + stats = new MicroStats(data); graph.setDataSet(data); - stats.setData(data); + statsTable.setStats(stats); raw.setData(data); setTitle(data.name); return this; @@ -232,18 +234,18 @@ public class MicroPeak extends MicroFrame implements ActionListener, ItemListene addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { - stats.tell_closing(); + statsTable.tell_closing(); Close(); } }); enable = new AltosUIEnable(); graph = new MicroGraph(enable); - stats = new MicroStatsTable(); + statsTable = new MicroStatsTable(); raw = new MicroRaw(); pane.add(graph.panel, "Graph"); pane.add(enable, "Configure Graph"); - pane.add(stats, "Statistics"); + pane.add(statsTable, "Statistics"); JScrollPane scroll = new JScrollPane(raw); pane.add(scroll, "Raw Data"); pane.doLayout(); diff --git a/micropeak/MicroStats.java b/micropeak/MicroStats.java index abc1296b..99479cb4 100644 --- a/micropeak/MicroStats.java +++ b/micropeak/MicroStats.java @@ -150,6 +150,43 @@ public class MicroStats { return descent_height() / descent_duration(); } + public static final int state_startup = -1; + public static final int state_pad = 0; + public static final int state_boost = 1; + public static final int state_coast = 2; + public static final int state_descent = 3; + public static final int state_landed = 4; + + static final String state_names[] = { + "pad", + "boost", + "coast", + "descent", + "landed" + }; + + public int state(double t) { + if (t >= landed_time) + return state_landed; + if (t >= apogee_time) + return state_descent; + if (t >= coast_time) + return state_coast; + if (t >= 0) + return state_boost; + return state_pad; + } + + public static String state_name(int state) { + if (state < 0 || state > state_landed) + return "unknown"; + return state_names[state]; + } + + public String state_name(double t) { + return state_name(state(t)); + } + public MicroStats(MicroData data) { this.data = data; diff --git a/micropeak/MicroStatsTable.java b/micropeak/MicroStatsTable.java index 5bdf5cb6..145bb70e 100644 --- a/micropeak/MicroStatsTable.java +++ b/micropeak/MicroStatsTable.java @@ -116,10 +116,6 @@ public class MicroStatsTable extends JComponent implements AltosFontListener { set_font(); } - public void setData(MicroData data) { - setStats(new MicroStats(data)); - } - public MicroStatsTable(MicroStats stats) { layout = new GridBagLayout(); -- cgit v1.2.3