Added functionality to plot multiple signals at the same time

This commit is contained in:
Henning Pohl 2015-10-23 18:18:42 +02:00
parent c102995e92
commit fe96ab9f44
3 changed files with 109 additions and 34 deletions

View File

@ -23,6 +23,7 @@ import processing.app.helpers.CircularBuffer;
import processing.app.helpers.Ticks;
import processing.app.legacy.PApplet;
import java.util.ArrayList;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.awt.*;
@ -35,24 +36,73 @@ import static processing.app.I18n.tr;
public class SerialPlotter extends AbstractMonitor {
private final StringBuffer messageBuffer;
private CircularBuffer buffer;
private JComboBox<String> serialRates;
private Serial serial;
private int serialRate;
private ArrayList<Graph> graphs;
private final static int BUFFER_CAPACITY = 500;
private static class Graph {
public CircularBuffer buffer;
private Color color;
public Graph(int id) {
buffer = new CircularBuffer(BUFFER_CAPACITY);
color = Theme.getColorCycleColor("plotting.graphcolor", id);
}
public void paint(Graphics2D g, float xstep, double minY,
double maxY, double rangeY, double height) {
g.setColor(color);
g.setStroke(new BasicStroke(1.0f));
for (int i = 0; i < buffer.size() - 1; ++i) {
g.drawLine(
(int) (i * xstep), (int) transformY(buffer.get(i), minY, rangeY, height),
(int) ((i + 1) * xstep), (int) transformY(buffer.get(i + 1), minY, rangeY, height)
);
}
}
private float transformY(double rawY, double minY, double rangeY, double height) {
return (float) (5 + (height - 10) * (1.0 - (rawY - minY) / rangeY));
}
}
private class GraphPanel extends JPanel {
private double minY, maxY, rangeY;
private Rectangle bounds;
private int xOffset;
private final Font font;
private final Color graphColor;
private final Color bgColor;
public GraphPanel() {
font = Theme.getFont("console.font");
graphColor = Theme.getColor("header.bgcolor");
bgColor = Theme.getColor("plotting.bgcolor");
xOffset = 20;
}
private Ticks computeBounds() {
minY = Double.POSITIVE_INFINITY;
maxY = Double.NEGATIVE_INFINITY;
for(Graph g : graphs) {
double bMin = g.buffer.min() / 2.0;
double bMax = g.buffer.max() * 2.0;
minY = bMin < minY ? bMin : minY;
maxY = bMax > maxY ? bMax : maxY;
}
Ticks ticks = new Ticks(minY, maxY, 3);
minY = Math.min(minY, ticks.getTick(0));
maxY = Math.max(maxY, ticks.getTick(ticks.getTickCount() - 1));
rangeY = maxY - minY;
minY -= 0.05 * rangeY;
maxY += 0.05 * rangeY;
rangeY = maxY - minY;
return ticks;
}
@Override
public void paintComponent(Graphics g1) {
Graphics2D g = (Graphics2D) g1;
@ -61,20 +111,12 @@ public class SerialPlotter extends AbstractMonitor {
super.paintComponent(g);
bounds = g.getClipBounds();
setBackground(Color.WHITE);
if (buffer.isEmpty()) {
setBackground(bgColor);
if (graphs.isEmpty()) {
return;
}
minY = buffer.min() / 2;
maxY = buffer.max() * 2;
Ticks ticks = new Ticks(minY, maxY, 3);
minY = Math.min(minY, ticks.getTick(0));
maxY = Math.max(maxY, ticks.getTick(ticks.getTickCount() - 1));
rangeY = maxY - minY;
minY -= 0.05 * rangeY;
maxY += 0.05 * rangeY;
rangeY = maxY - minY;
Ticks ticks = computeBounds();
g.setStroke(new BasicStroke(1.0f));
FontMetrics fm = g.getFontMetrics();
@ -92,19 +134,21 @@ public class SerialPlotter extends AbstractMonitor {
g.drawLine(bounds.x + xOffset, bounds.y + 5, bounds.x + xOffset, bounds.y + bounds.height - 10);
g.setTransform(AffineTransform.getTranslateInstance(xOffset, 0));
float xstep = (float) (bounds.width - xOffset) / (float) buffer.capacity();
float xstep = (float) (bounds.width - xOffset) / (float) BUFFER_CAPACITY;
int legendLength = graphs.size() * 10 + (graphs.size() - 1) * 3;
g.setColor(graphColor);
g.setStroke(new BasicStroke(0.75f));
for (int i = 0; i < buffer.size() - 1; ++i) {
g.drawLine(
(int) (i * xstep), (int) transformY(buffer.get(i)),
(int) ((i + 1) * xstep), (int) transformY(buffer.get(i + 1))
);
for(int i = 0; i < graphs.size(); ++i) {
graphs.get(i).paint(g, xstep, minY, maxY, rangeY, bounds.height);
if(graphs.size() > 1) {
g.fillRect(bounds.width - (xOffset + legendLength + 10) + i * 13, 10, 10, 10);
}
}
}
private float transformY(double rawY) {
return (float) (5 + (bounds.height - 10) * (1.0 - (rawY - minY) / rangeY));
}
@Override
public Dimension getMinimumSize() {
return new Dimension(200, 100);
@ -114,10 +158,6 @@ public class SerialPlotter extends AbstractMonitor {
public Dimension getPreferredSize() {
return new Dimension(500, 250);
}
private float transformY(double rawY) {
return (float) (5 + (bounds.height - 10) * (1.0 - (rawY - minY) / rangeY));
}
}
public SerialPlotter(BoardPort port) {
@ -140,12 +180,12 @@ public class SerialPlotter extends AbstractMonitor {
});
messageBuffer = new StringBuffer();
graphs = new ArrayList<Graph>();
}
protected void onCreateWindow(Container mainPane) {
mainPane.setLayout(new BorderLayout());
buffer = new CircularBuffer(500);
GraphPanel graphPanel = new GraphPanel();
mainPane.add(graphPanel, BorderLayout.CENTER);
@ -182,14 +222,26 @@ public class SerialPlotter extends AbstractMonitor {
}
String line = messageBuffer.substring(0, linebreak);
line = line.trim();
messageBuffer.delete(0, linebreak + 1);
try {
double value = Double.valueOf(line);
buffer.add(value);
} catch (NumberFormatException e) {
// ignore
line = line.trim();
String[] parts = line.split("[, ]+");
if(parts.length == 0) {
continue;
}
int validParts = 0;
for(int i = 0; i < parts.length; ++i) {
try {
double value = Double.valueOf(parts[i]);
if(i >= graphs.size()) {
graphs.add(new Graph(validParts));
}
graphs.get(validParts).buffer.add(value);
validParts++;
} catch (NumberFormatException e) {
// ignore
}
}
}

View File

@ -94,6 +94,19 @@ public class Theme {
set(key, String.valueOf(value));
}
static public Color getColorCycleColor(String name, int i) {
int cycleSize = getInteger(name + ".size");
name = String.format("%s.%02d", name, i % cycleSize);
return PreferencesHelper.parseColor(get(name));
}
static public void setColorCycleColor(String name, int i, Color color) {
name = String.format("%s.%02d", name, i);
PreferencesHelper.putColor(table, name, color);
int cycleSize = getInteger(name + ".size");
setInteger(name + ".size", (i + 1) > cycleSize ? (i + 1) : cycleSize);
}
static public Color getColor(String name) {
return PreferencesHelper.parseColor(get(name));
}

View File

@ -37,6 +37,16 @@ buttons.bgcolor = #006468
buttons.status.font = SansSerif,plain,12
buttons.status.color = #ffffff
# GUI - PLOTTING
# color cycle created via colorbrewer2.org
plotting.bgcolor = #ffffff
plotting.color = #ffffff
plotting.graphcolor.size = 4
plotting.graphcolor.00 = #2c7bb6
plotting.graphcolor.01 = #fdae61
plotting.graphcolor.02 = #d7191c
plotting.graphcolor.03 = #abd9e9
# GUI - LINESTATUS
linestatus.color = #ffffff
linestatus.bgcolor = #006468