From 6928a77135535b007a09d3ee4ccfedf9664b2028 Mon Sep 17 00:00:00 2001 From: Oblivion409 Date: Fri, 1 Jul 2022 20:23:40 -0400 Subject: [PATCH 01/10] Add multi-plot support with Window --- .../stuylib/util/plot/Playground.java | 36 ++++++++---- src/com/stuypulse/stuylib/util/plot/Plot.java | 23 ++------ .../stuypulse/stuylib/util/plot/Settings.java | 55 +------------------ .../stuypulse/stuylib/util/plot/Window.java | 52 ++++++++++++++++++ 4 files changed, 81 insertions(+), 85 deletions(-) create mode 100644 src/com/stuypulse/stuylib/util/plot/Window.java diff --git a/src/com/stuypulse/stuylib/util/plot/Playground.java b/src/com/stuypulse/stuylib/util/plot/Playground.java index d032a6d8..53175141 100644 --- a/src/com/stuypulse/stuylib/util/plot/Playground.java +++ b/src/com/stuypulse/stuylib/util/plot/Playground.java @@ -25,8 +25,8 @@ public interface Constants { String X_AXIS = "x-axis"; String Y_AXIS = "y-axis"; - int WIDTH = 800; - int HEIGHT = 600; + int WIDTH = 1600; + int HEIGHT = 1200; double MIN_X = 0.0; double MAX_X = 1.0; @@ -36,7 +36,6 @@ public interface Constants { Settings SETTINGS = new Settings() - .setSize(WIDTH, HEIGHT) .setAxes(TITLE, X_AXIS, Y_AXIS) .setXRange(MIN_X, MAX_X) .setYRange(MIN_Y, MAX_Y); @@ -59,9 +58,8 @@ public static Series make(String id, BStream series) { } public static void main(String[] args) throws InterruptedException { - Plot plot = new Plot(Constants.SETTINGS); - - plot.addSeries(Constants.make("y=x", x -> x)) + Plot fplot = new Plot(Constants.SETTINGS) + .addSeries(Constants.make("y=x", x -> x)) .addSeries( Constants.make( "interp", @@ -71,8 +69,11 @@ public static void main(String[] args) throws InterruptedException { new Vector2D(0.4, 0.72), new Vector2D(0.6, 0.81), new Vector2D(0.8, 0.02), - new Vector2D(1.0, 0.11)))) - .addSeries(Constants.make("mouse y", IStream.create(plot::getMouseY))) + new Vector2D(1.0, 0.11)))); + + Plot plot = new Plot(Constants.SETTINGS); + + plot.addSeries(Constants.make("mouse y", IStream.create(plot::getMouseY))) .addSeries( Constants.make( "lpf", @@ -83,16 +84,27 @@ public static void main(String[] args) throws InterruptedException { Constants.make( "debounced", BStream.create(() -> plot.getMouseY() > 0.5) - .filtered(new BDebounce.Both(1.0)))) - .addSeries(Constants.make("mouse position", VStream.create(plot::getMouse))) + .filtered(new BDebounce.Both(1.0)))); + + Plot vplot = new Plot(Constants.SETTINGS); + + vplot.addSeries(Constants.make("mouse position", VStream.create(plot::getMouse))) .addSeries( Constants.make( "jerk limit", VStream.create(plot::getMouse) .filtered(new VJerkLimit(10.0, 5.0)))); - while (plot.isRunning()) { - plot.update(); + Window window = new Window( + Constants.TITLE, + Constants.WIDTH, + Constants.HEIGHT, + plot, + fplot, + vplot); + + for (;;) { + window.update(); Thread.sleep(20); } } diff --git a/src/com/stuypulse/stuylib/util/plot/Plot.java b/src/com/stuypulse/stuylib/util/plot/Plot.java index c0c90e65..cd893206 100644 --- a/src/com/stuypulse/stuylib/util/plot/Plot.java +++ b/src/com/stuypulse/stuylib/util/plot/Plot.java @@ -6,11 +6,9 @@ import com.stuypulse.stuylib.math.Vector2D; -import java.awt.Dimension; import java.awt.Toolkit; import java.util.ArrayList; import java.util.List; -import javax.swing.JFrame; import org.knowm.xchart.XChartPanel; import org.knowm.xchart.XYChart; import org.knowm.xchart.XYChartBuilder; @@ -28,9 +26,6 @@ public class Plot { /** A collection of Series to be graphed */ private List plots; - /** The window that is created */ - private JFrame frame; - /** A reference to the XChart library */ private XYChart instance; @@ -51,12 +46,6 @@ public Plot(Settings settings) { // Setup series plots = new ArrayList<>(); - // Setup window - frame = new JFrame(settings.getTitle()); - - frame.getContentPane() - .setPreferredSize(new Dimension(settings.getWidth(), settings.getHeight())); - frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // Create XYChart using settings instance = @@ -77,14 +66,6 @@ public Plot(Settings settings) { mouse = new MouseTracker(panel); - frame.getContentPane().add(panel); - frame.setResizable(false); - - frame.pack(); - - frame.setLocationRelativeTo(null); - frame.setVisible(true); - runOnce = true; } @@ -108,6 +89,10 @@ public double getMouseX() { return mouse.getX(); } + protected XChartPanel getPanel() { + return panel; + } + /** * Adds series to be graphed * diff --git a/src/com/stuypulse/stuylib/util/plot/Settings.java b/src/com/stuypulse/stuylib/util/plot/Settings.java index 4290a204..b4a96a31 100644 --- a/src/com/stuypulse/stuylib/util/plot/Settings.java +++ b/src/com/stuypulse/stuylib/util/plot/Settings.java @@ -39,11 +39,6 @@ public Axes(String title, String x, String y) { private String xAxis; private String yAxis; - /** window size */ - private int width; - - private int height; - /** x-axis bounds */ private double xMin; @@ -60,9 +55,6 @@ public Settings() { xAxis = "x"; yAxis = "y"; - width = 640; - height = 480; - xMin = 0.0; xMax = 1.0; @@ -85,16 +77,6 @@ public String getYAxis() { return yAxis; } - /** @return width of window */ - public int getWidth() { - return width; - } - - /** @return height of window */ - public int getHeight() { - return height; - } - /** @return lower bound of x-axis */ public double getXMin() { return xMin; @@ -115,7 +97,7 @@ public double getYMax() { return yMax; } - /** + /** * Sets title of plot * * @param title title @@ -242,39 +224,4 @@ public Settings setYRange(double min, double max) { setYMin(min); return this; } - - /** - * Sets width of window - * - * @param width width of window - * @return reference to self for chaining methods - */ - public Settings setWidth(int width) { - this.width = width; - return this; - } - - /** - * Sets height of window - * - * @param height height of window - * @return reference to self for chaining methods - */ - public Settings setHeight(int height) { - this.height = height; - return this; - } - - /** - * Sets size of window - * - * @param width width of window - * @param height height of window - * @return reference to self for chaining methods - */ - public Settings setSize(int width, int height) { - setWidth(width); - setHeight(height); - return this; - } } diff --git a/src/com/stuypulse/stuylib/util/plot/Window.java b/src/com/stuypulse/stuylib/util/plot/Window.java new file mode 100644 index 00000000..e52cb81f --- /dev/null +++ b/src/com/stuypulse/stuylib/util/plot/Window.java @@ -0,0 +1,52 @@ +package com.stuypulse.stuylib.util.plot; + +import java.awt.Dimension; +import java.awt.GridLayout; +import java.util.Arrays; +import java.util.List; + +import javax.swing.JFrame; + +public class Window { + + public static void createWindow(Plot... graphs) { + + } + + private List graphs; + + public Window(String title, int width, int height, Plot... plots) { + graphs = Arrays.asList(plots); + + JFrame frame = new JFrame(title); + + frame.getContentPane() + .setPreferredSize(new Dimension(width, height)); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + frame.setResizable(false); + + // from SwingWrapper.java from XChart + int rows = (int) (Math.sqrt(graphs.size()) + .5); + int cols = (int) ((double) graphs.size() / rows + 1); + + frame.getContentPane().setLayout(new GridLayout(rows, cols)); + + for (Plot plot : graphs) { + frame.add(plot.getPanel()); + } + + frame.pack(); + + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + public void update() { + for (Plot plot : graphs) { + if (plot.isRunning()) + plot.update(); + } + } + +} From e0e708a4f3792abf308ccd631c408b114f894693 Mon Sep 17 00:00:00 2001 From: Oblivion409 Date: Fri, 1 Jul 2022 20:27:04 -0400 Subject: [PATCH 02/10] h --- src/com/stuypulse/stuylib/util/plot/Window.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/com/stuypulse/stuylib/util/plot/Window.java b/src/com/stuypulse/stuylib/util/plot/Window.java index e52cb81f..8d995e81 100644 --- a/src/com/stuypulse/stuylib/util/plot/Window.java +++ b/src/com/stuypulse/stuylib/util/plot/Window.java @@ -9,10 +9,6 @@ public class Window { - public static void createWindow(Plot... graphs) { - - } - private List graphs; public Window(String title, int width, int height, Plot... plots) { From c42faa9cbd8618e1e62d160d7fe23c2cd3231227 Mon Sep 17 00:00:00 2001 From: Oblivion409 Date: Sat, 2 Jul 2022 15:08:28 -0400 Subject: [PATCH 03/10] Restructure tiled plots to use Tab class --- .../stuylib/util/plot/Playground.java | 88 ++++++------ src/com/stuypulse/stuylib/util/plot/Plot.java | 135 ++++++++---------- src/com/stuypulse/stuylib/util/plot/Tab.java | 87 +++++++++++ .../stuypulse/stuylib/util/plot/Window.java | 48 ------- 4 files changed, 185 insertions(+), 173 deletions(-) create mode 100644 src/com/stuypulse/stuylib/util/plot/Tab.java delete mode 100644 src/com/stuypulse/stuylib/util/plot/Window.java diff --git a/src/com/stuypulse/stuylib/util/plot/Playground.java b/src/com/stuypulse/stuylib/util/plot/Playground.java index 53175141..6efcd69f 100644 --- a/src/com/stuypulse/stuylib/util/plot/Playground.java +++ b/src/com/stuypulse/stuylib/util/plot/Playground.java @@ -25,8 +25,8 @@ public interface Constants { String X_AXIS = "x-axis"; String Y_AXIS = "y-axis"; - int WIDTH = 1600; - int HEIGHT = 1200; + int WIDTH = 1200; + int HEIGHT = 800; double MIN_X = 0.0; double MAX_X = 1.0; @@ -58,53 +58,45 @@ public static Series make(String id, BStream series) { } public static void main(String[] args) throws InterruptedException { - Plot fplot = new Plot(Constants.SETTINGS) - .addSeries(Constants.make("y=x", x -> x)) - .addSeries( - Constants.make( - "interp", - new LinearInterpolator( - new Vector2D(0.0, 0.43), - new Vector2D(0.2, 0.56), - new Vector2D(0.4, 0.72), - new Vector2D(0.6, 0.81), - new Vector2D(0.8, 0.02), - new Vector2D(1.0, 0.11)))); - - Plot plot = new Plot(Constants.SETTINGS); - - plot.addSeries(Constants.make("mouse y", IStream.create(plot::getMouseY))) - .addSeries( - Constants.make( - "lpf", - IStream.create(plot::getMouseY).filtered(new LowPassFilter(0.2)))) - .addSeries( - Constants.make("mouse bool", BStream.create(() -> plot.getMouseY() > 0.5))) - .addSeries( - Constants.make( - "debounced", - BStream.create(() -> plot.getMouseY() > 0.5) - .filtered(new BDebounce.Both(1.0)))); - - Plot vplot = new Plot(Constants.SETTINGS); - - vplot.addSeries(Constants.make("mouse position", VStream.create(plot::getMouse))) - .addSeries( - Constants.make( - "jerk limit", - VStream.create(plot::getMouse) - .filtered(new VJerkLimit(10.0, 5.0)))); - - Window window = new Window( - Constants.TITLE, - Constants.WIDTH, - Constants.HEIGHT, - plot, - fplot, - vplot); - + Plot plot = new Plot(); + + plot.addPlot(Constants.SETTINGS.setTitle("Functions")) + .addSeries("Functions", + Constants.make("y=x", x -> x), + Constants.make( + "interp", + new LinearInterpolator( + new Vector2D(0.0, 0.43), + new Vector2D(0.2, 0.56), + new Vector2D(0.4, 0.72), + new Vector2D(0.6, 0.81), + new Vector2D(0.8, 0.02), + new Vector2D(1.0, 0.11)))) + + .addPlot(Constants.SETTINGS.setTitle("Filters")) + .addSeries("Filters", + Constants.make("mouse y", IStream.create(plot::getMouseY)), + Constants.make( + "lpf", + IStream.create(plot::getMouseY).filtered(new LowPassFilter(0.2))), + Constants.make("mouse bool", BStream.create(() -> plot.getMouseY() > 0.5)), + Constants.make( + "debounced", + BStream.create(() -> plot.getMouseY() > 0.5) + .filtered(new BDebounce.Both(1.0)))) + + .addPlot(Constants.SETTINGS.setTitle("XY Graph")) + .addSeries("XY Graph", + Constants.make("mouse position", VStream.create(plot::getMouse)), + Constants.make( + "jerk limit", + VStream.create(plot::getMouse) + .filtered(new VJerkLimit(10.0, 5.0)))) + + .build(Constants.TITLE, Constants.WIDTH, Constants.HEIGHT); + for (;;) { - window.update(); + plot.update(); Thread.sleep(20); } } diff --git a/src/com/stuypulse/stuylib/util/plot/Plot.java b/src/com/stuypulse/stuylib/util/plot/Plot.java index cd893206..a816ba27 100644 --- a/src/com/stuypulse/stuylib/util/plot/Plot.java +++ b/src/com/stuypulse/stuylib/util/plot/Plot.java @@ -6,12 +6,12 @@ import com.stuypulse.stuylib.math.Vector2D; -import java.awt.Toolkit; -import java.util.ArrayList; -import java.util.List; -import org.knowm.xchart.XChartPanel; -import org.knowm.xchart.XYChart; -import org.knowm.xchart.XYChartBuilder; +import java.awt.Dimension; +import java.awt.GridLayout; +import java.util.HashMap; +import java.util.Map; + +import javax.swing.JFrame; /** * A plot contains and manages the window to which any data is drawn. @@ -23,55 +23,59 @@ */ public class Plot { - /** A collection of Series to be graphed */ - private List plots; + private Map tabs; - /** A reference to the XChart library */ - private XYChart instance; + private String defaultTab; - private XChartPanel panel; + private JFrame frame; /** A utility for finding mouse positions */ private MouseTracker mouse; - /** A boolean to ensure the plot is updated at least once */ - private boolean runOnce; - /** * Creates a configured plot - * - * @param settings plot & window settings */ - public Plot(Settings settings) { - // Setup series - plots = new ArrayList<>(); - - - // Create XYChart using settings - instance = - new XYChartBuilder() - .title(settings.getTitle()) - .xAxisTitle(settings.getXAxis()) - .yAxisTitle(settings.getYAxis()) - .build(); - - instance.getStyler().setYAxisMin(settings.getYMin()); - instance.getStyler().setYAxisMax(settings.getYMax()); + public Plot() { + tabs = new HashMap(); - instance.getStyler().setXAxisMin(settings.getXMin()); - instance.getStyler().setXAxisMax(settings.getXMax()); + defaultTab = null; + } + + public void build(String title, int width, int height) { + frame = new JFrame(title); + + frame.getContentPane() + .setPreferredSize(new Dimension(width, height)); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + frame.setResizable(false); + + // from SwingWrapper.java from XChart + int rows = (int) (Math.sqrt(tabs.size()) + .5); + int cols = (int) ((double) tabs.size() / rows + 1); + + frame.getContentPane().setLayout(new GridLayout(rows, cols)); + + for (String tab : tabs.keySet()) { + frame.add(tabs.get(tab).panel); + } + + frame.pack(); + + frame.setLocationRelativeTo(null); + frame.setVisible(true); + + mouse = new MouseTracker(frame); + } - panel = new XChartPanel(instance); - panel.setName(settings.getTitle()); + public Plot addPlot(Settings settings) { + Tab tab = new Tab(settings); - mouse = new MouseTracker(panel); + tabs.put(settings.getTitle(), tab); - runOnce = true; - } + if (defaultTab == null) defaultTab = settings.getTitle(); - /** Creates a plot with default settings */ - public Plot() { - this(new Settings()); + return this; } /** @return mouse position */ @@ -89,54 +93,31 @@ public double getMouseX() { return mouse.getX(); } - protected XChartPanel getPanel() { - return panel; - } - /** * Adds series to be graphed * * @param series series to add * @return reference to self */ - public Plot addSeries(Series... series) { - for (Series e : series) plots.add(e); - return this; - } - - /** allows the series to update the XYChart */ - public void updateSeries() { - for (Series plot : plots) { - plot.update(instance); + public Plot addSeries(String tabId, Series... series) { + if (!tabs.containsKey(tabId)) { + System.err.println("Invalid tab ID \"" + tabId + "\" given"); + return this; } - } - /** repaints the screen */ - public void display() { - Toolkit.getDefaultToolkit().sync(); - panel.revalidate(); - panel.repaint(); + tabs.get(tabId).addSeries(series); + return this; } - public void update() { - updateSeries(); - display(); + public Plot addSeries(Series... series) { + return addSeries(defaultTab, series); } - /** - * Checks if any series are polling to see if the plot should still update. - * - * @return if the plot should still run - */ - public boolean isRunning() { - if (runOnce) { - runOnce = false; - return true; - } - - for (Series e : plots) { - if (e.isPolling()) return true; + public void update() { + for (String key : tabs.keySet()) { + Tab tab = tabs.get(key); + + if (tab.isRunning()) tab.update(); } - return false; } } diff --git a/src/com/stuypulse/stuylib/util/plot/Tab.java b/src/com/stuypulse/stuylib/util/plot/Tab.java new file mode 100644 index 00000000..1a8f913d --- /dev/null +++ b/src/com/stuypulse/stuylib/util/plot/Tab.java @@ -0,0 +1,87 @@ +package com.stuypulse.stuylib.util.plot; + +import java.awt.Toolkit; +import java.util.ArrayList; +import java.util.List; + +import org.knowm.xchart.XChartPanel; +import org.knowm.xchart.XYChart; +import org.knowm.xchart.XYChartBuilder; + +public class Tab { + + /** A collection of Series to be graphed */ + private List plots; + + private XYChart instance; + + protected XChartPanel panel; + + /** A boolean to ensure the plot is updated at least once */ + private boolean runOnce; + + public Tab(Settings settings) { + // Setup series + plots = new ArrayList<>(); + + // Create XYChart using settings + instance = + new XYChartBuilder() + .title(settings.getTitle()) + .xAxisTitle(settings.getXAxis()) + .yAxisTitle(settings.getYAxis()) + .build(); + + instance.getStyler().setYAxisMin(settings.getYMin()); + instance.getStyler().setYAxisMax(settings.getYMax()); + + instance.getStyler().setXAxisMin(settings.getXMin()); + instance.getStyler().setXAxisMax(settings.getXMax()); + + panel = new XChartPanel(instance); + panel.setName(settings.getTitle()); + + runOnce = true; + } + + public void addSeries(Series... series) { + for (Series s : series) plots.add(s); + } + + /** allows the series to update the XYChart */ + public void updateSeries() { + for (Series plot : plots) { + plot.update(instance); + } + } + + /** repaints the screen */ + public void display() { + Toolkit.getDefaultToolkit().sync(); + panel.revalidate(); + panel.repaint(); + } + + public void update() { + updateSeries(); + display(); + } + + /** + * Checks if any series are polling to see if the plot should still update. + * + * @return if the plot should still run + */ + public boolean isRunning() { + if (runOnce) { + runOnce = false; + return true; + } + + for (Series e : plots) { + if (e.isPolling()) return true; + } + return false; + } + +} diff --git a/src/com/stuypulse/stuylib/util/plot/Window.java b/src/com/stuypulse/stuylib/util/plot/Window.java deleted file mode 100644 index 8d995e81..00000000 --- a/src/com/stuypulse/stuylib/util/plot/Window.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.stuypulse.stuylib.util.plot; - -import java.awt.Dimension; -import java.awt.GridLayout; -import java.util.Arrays; -import java.util.List; - -import javax.swing.JFrame; - -public class Window { - - private List graphs; - - public Window(String title, int width, int height, Plot... plots) { - graphs = Arrays.asList(plots); - - JFrame frame = new JFrame(title); - - frame.getContentPane() - .setPreferredSize(new Dimension(width, height)); - frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - - frame.setResizable(false); - - // from SwingWrapper.java from XChart - int rows = (int) (Math.sqrt(graphs.size()) + .5); - int cols = (int) ((double) graphs.size() / rows + 1); - - frame.getContentPane().setLayout(new GridLayout(rows, cols)); - - for (Plot plot : graphs) { - frame.add(plot.getPanel()); - } - - frame.pack(); - - frame.setLocationRelativeTo(null); - frame.setVisible(true); - } - - public void update() { - for (Plot plot : graphs) { - if (plot.isRunning()) - plot.update(); - } - } - -} From a435c875e218b39d75219a6e27286b7d4c51daa6 Mon Sep 17 00:00:00 2001 From: Oblivion409 Date: Sat, 2 Jul 2022 17:45:03 -0400 Subject: [PATCH 04/10] Change Plot to display tabs instead of grid layout --- .../stuylib/util/plot/Playground.java | 4 +- src/com/stuypulse/stuylib/util/plot/Plot.java | 51 ++++++++++--------- 2 files changed, 29 insertions(+), 26 deletions(-) diff --git a/src/com/stuypulse/stuylib/util/plot/Playground.java b/src/com/stuypulse/stuylib/util/plot/Playground.java index 6efcd69f..e809dedf 100644 --- a/src/com/stuypulse/stuylib/util/plot/Playground.java +++ b/src/com/stuypulse/stuylib/util/plot/Playground.java @@ -25,8 +25,8 @@ public interface Constants { String X_AXIS = "x-axis"; String Y_AXIS = "y-axis"; - int WIDTH = 1200; - int HEIGHT = 800; + int WIDTH = 640; + int HEIGHT = 480; double MIN_X = 0.0; double MAX_X = 1.0; diff --git a/src/com/stuypulse/stuylib/util/plot/Plot.java b/src/com/stuypulse/stuylib/util/plot/Plot.java index a816ba27..46b05cd8 100644 --- a/src/com/stuypulse/stuylib/util/plot/Plot.java +++ b/src/com/stuypulse/stuylib/util/plot/Plot.java @@ -7,11 +7,13 @@ import com.stuypulse.stuylib.math.Vector2D; import java.awt.Dimension; -import java.awt.GridLayout; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; import javax.swing.JFrame; +import javax.swing.JTabbedPane; /** * A plot contains and manages the window to which any data is drawn. @@ -23,11 +25,12 @@ */ public class Plot { - private Map tabs; - - private String defaultTab; + private List tabs; + private Map names; + private int defaultTab; private JFrame frame; + private JTabbedPane pane; /** A utility for finding mouse positions */ private MouseTracker mouse; @@ -36,12 +39,15 @@ public class Plot { * Creates a configured plot */ public Plot() { - tabs = new HashMap(); + tabs = new ArrayList(); + names = new HashMap(); - defaultTab = null; + defaultTab = 0; } public void build(String title, int width, int height) { + pane = new JTabbedPane(); + frame = new JFrame(title); frame.getContentPane() @@ -50,16 +56,12 @@ public void build(String title, int width, int height) { frame.setResizable(false); - // from SwingWrapper.java from XChart - int rows = (int) (Math.sqrt(tabs.size()) + .5); - int cols = (int) ((double) tabs.size() / rows + 1); - - frame.getContentPane().setLayout(new GridLayout(rows, cols)); - - for (String tab : tabs.keySet()) { - frame.add(tabs.get(tab).panel); + for (Tab tab : tabs) { + pane.addTab(tab.panel.getName(), tab.panel); } + frame.getContentPane().add(pane); + frame.pack(); frame.setLocationRelativeTo(null); @@ -71,9 +73,10 @@ public void build(String title, int width, int height) { public Plot addPlot(Settings settings) { Tab tab = new Tab(settings); - tabs.put(settings.getTitle(), tab); + tabs.add(tab); + names.put(settings.getTitle(), tabs.size() - 1); - if (defaultTab == null) defaultTab = settings.getTitle(); + defaultTab = tabs.size() - 1; return this; } @@ -100,24 +103,24 @@ public double getMouseX() { * @return reference to self */ public Plot addSeries(String tabId, Series... series) { - if (!tabs.containsKey(tabId)) { + if (!names.containsKey(tabId)) { System.err.println("Invalid tab ID \"" + tabId + "\" given"); return this; } - tabs.get(tabId).addSeries(series); + tabs.get(names.get(tabId)).addSeries(series); return this; } public Plot addSeries(Series... series) { - return addSeries(defaultTab, series); + tabs.get(defaultTab).addSeries(series); + return this; } public void update() { - for (String key : tabs.keySet()) { - Tab tab = tabs.get(key); - - if (tab.isRunning()) tab.update(); - } + int selected = pane.getSelectedIndex(); + + if (tabs.get(selected).isRunning()) + tabs.get(selected).update(); } } From 5bc0dd3dab515beb66e242c2349d9f2283f2f556 Mon Sep 17 00:00:00 2001 From: Oblivion409 Date: Sat, 2 Jul 2022 22:02:33 -0400 Subject: [PATCH 05/10] Add DataSeries to plot 2d points --- .../stuylib/util/plot/DataSeries.java | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 src/com/stuypulse/stuylib/util/plot/DataSeries.java diff --git a/src/com/stuypulse/stuylib/util/plot/DataSeries.java b/src/com/stuypulse/stuylib/util/plot/DataSeries.java new file mode 100644 index 00000000..963ab271 --- /dev/null +++ b/src/com/stuypulse/stuylib/util/plot/DataSeries.java @@ -0,0 +1,50 @@ +/* Copyright (c) 2022 StuyPulse Robotics. All rights reserved. */ +/* This work is licensed under the terms of the MIT license */ +/* found in the root directory of this project. */ + +package com.stuypulse.stuylib.util.plot; + +import java.util.ArrayList; +import java.util.List; + +import com.stuypulse.stuylib.math.Vector2D; + +public class DataSeries extends Series { + + private List xValues; + private List yValues; + + public DataSeries(String label, Vector2D... points) { + super(new Config(label, points.length), false); + + xValues = new ArrayList(); + yValues = new ArrayList(); + + for (Vector2D point : points) { + xValues.add(point.x); + yValues.add(point.y); + } + } + + @Override + public int size() { + return yValues.size(); + } + + @Override + protected List getSafeXValues() { + return xValues; + } + + @Override + protected List getSafeYValues() { + return yValues; + } + + @Override + protected void pop() {} + + @Override + protected void poll() {} + +} From 18e152b4c591c904031790001fe2a4a531a22f3f Mon Sep 17 00:00:00 2001 From: BenG49 <64862590+BenG49@users.noreply.github.com> Date: Wed, 6 Jul 2022 16:02:23 -0400 Subject: [PATCH 06/10] Remove defaultTab, by default use most recent Tab in Plot --- src/com/stuypulse/stuylib/util/plot/Plot.java | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/com/stuypulse/stuylib/util/plot/Plot.java b/src/com/stuypulse/stuylib/util/plot/Plot.java index 46b05cd8..b6965c55 100644 --- a/src/com/stuypulse/stuylib/util/plot/Plot.java +++ b/src/com/stuypulse/stuylib/util/plot/Plot.java @@ -27,7 +27,6 @@ public class Plot { private List tabs; private Map names; - private int defaultTab; private JFrame frame; private JTabbedPane pane; @@ -41,8 +40,6 @@ public class Plot { public Plot() { tabs = new ArrayList(); names = new HashMap(); - - defaultTab = 0; } public void build(String title, int width, int height) { @@ -76,8 +73,6 @@ public Plot addPlot(Settings settings) { tabs.add(tab); names.put(settings.getTitle(), tabs.size() - 1); - defaultTab = tabs.size() - 1; - return this; } @@ -113,7 +108,7 @@ public Plot addSeries(String tabId, Series... series) { } public Plot addSeries(Series... series) { - tabs.get(defaultTab).addSeries(series); + tabs.get(tabs.size() - 1).addSeries(series); return this; } From 89bb0bf472f527c0c07ef5991aa2fe500dd7d4e0 Mon Sep 17 00:00:00 2001 From: BenG49 <64862590+BenG49@users.noreply.github.com> Date: Wed, 6 Jul 2022 16:02:28 -0400 Subject: [PATCH 07/10] Refactor Playground --- .../stuylib/util/plot/Playground.java | 34 ++++++++++++------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/src/com/stuypulse/stuylib/util/plot/Playground.java b/src/com/stuypulse/stuylib/util/plot/Playground.java index e809dedf..8395b31c 100644 --- a/src/com/stuypulse/stuylib/util/plot/Playground.java +++ b/src/com/stuypulse/stuylib/util/plot/Playground.java @@ -40,6 +40,13 @@ public interface Constants { .setXRange(MIN_X, MAX_X) .setYRange(MIN_Y, MAX_Y); + public static Settings settings(String title) { + return new Settings() + .setAxes(title, X_AXIS, Y_AXIS) + .setXRange(MIN_X, MAX_X) + .setYRange(MIN_Y, MAX_Y); + } + public static Series make(String id, IFilter function) { return new FuncSeries(new Config(id, CAPACITY), new Domain(MIN_X, MAX_X), function); } @@ -60,9 +67,9 @@ public static Series make(String id, BStream series) { public static void main(String[] args) throws InterruptedException { Plot plot = new Plot(); - plot.addPlot(Constants.SETTINGS.setTitle("Functions")) - .addSeries("Functions", - Constants.make("y=x", x -> x), + plot.addPlot(Constants.settings("Functions")) + .addSeries(Constants.make("y=x", x -> x)) + .addSeries( Constants.make( "interp", new LinearInterpolator( @@ -73,22 +80,23 @@ public static void main(String[] args) throws InterruptedException { new Vector2D(0.8, 0.02), new Vector2D(1.0, 0.11)))) - .addPlot(Constants.SETTINGS.setTitle("Filters")) - .addSeries("Filters", - Constants.make("mouse y", IStream.create(plot::getMouseY)), + .addPlot(Constants.settings("Filters")) + .addSeries(Constants.make("mouse y", IStream.create(plot::getMouseY))) + .addSeries( Constants.make( "lpf", - IStream.create(plot::getMouseY).filtered(new LowPassFilter(0.2))), - Constants.make("mouse bool", BStream.create(() -> plot.getMouseY() > 0.5)), - Constants.make( + IStream.create(plot::getMouseY).filtered(new LowPassFilter(0.2)))) + .addSeries( + Constants.make("mouse bool", BStream.create(() -> plot.getMouseY() > 0.5))) + .addSeries( + Constants.make( "debounced", BStream.create(() -> plot.getMouseY() > 0.5) .filtered(new BDebounce.Both(1.0)))) - .addPlot(Constants.SETTINGS.setTitle("XY Graph")) - .addSeries("XY Graph", - Constants.make("mouse position", VStream.create(plot::getMouse)), - Constants.make( + .addPlot(Constants.settings("XY Graph")) + .addSeries(Constants.make("mouse position", VStream.create(plot::getMouse))) + .addSeries(Constants.make( "jerk limit", VStream.create(plot::getMouse) .filtered(new VJerkLimit(10.0, 5.0)))) From 23733ac08700922d073e881454cbfb8627701020 Mon Sep 17 00:00:00 2001 From: BenG49 <64862590+BenG49@users.noreply.github.com> Date: Thu, 28 Jul 2022 23:33:10 -0400 Subject: [PATCH 08/10] Move legend --- src/com/stuypulse/stuylib/util/plot/Tab.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/com/stuypulse/stuylib/util/plot/Tab.java b/src/com/stuypulse/stuylib/util/plot/Tab.java index 1a8f913d..a0a54e2d 100644 --- a/src/com/stuypulse/stuylib/util/plot/Tab.java +++ b/src/com/stuypulse/stuylib/util/plot/Tab.java @@ -7,6 +7,7 @@ import org.knowm.xchart.XChartPanel; import org.knowm.xchart.XYChart; import org.knowm.xchart.XYChartBuilder; +import org.knowm.xchart.style.Styler.LegendPosition; public class Tab { @@ -37,6 +38,8 @@ public Tab(Settings settings) { instance.getStyler().setXAxisMin(settings.getXMin()); instance.getStyler().setXAxisMax(settings.getXMax()); + + instance.getStyler().setLegendPosition(LegendPosition.InsideNW); panel = new XChartPanel(instance); panel.setName(settings.getTitle()); From 50f53fb28c9c0c015e84dc2f0bb3b01fd385d0b8 Mon Sep 17 00:00:00 2001 From: BenG49 <64862590+BenG49@users.noreply.github.com> Date: Thu, 28 Jul 2022 23:50:39 -0400 Subject: [PATCH 09/10] Rename addPlot to addTab --- src/com/stuypulse/stuylib/util/plot/Playground.java | 6 +++--- src/com/stuypulse/stuylib/util/plot/Plot.java | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/com/stuypulse/stuylib/util/plot/Playground.java b/src/com/stuypulse/stuylib/util/plot/Playground.java index 8395b31c..916898d1 100644 --- a/src/com/stuypulse/stuylib/util/plot/Playground.java +++ b/src/com/stuypulse/stuylib/util/plot/Playground.java @@ -67,7 +67,7 @@ public static Series make(String id, BStream series) { public static void main(String[] args) throws InterruptedException { Plot plot = new Plot(); - plot.addPlot(Constants.settings("Functions")) + plot.addTab(Constants.settings("Functions")) .addSeries(Constants.make("y=x", x -> x)) .addSeries( Constants.make( @@ -80,7 +80,7 @@ public static void main(String[] args) throws InterruptedException { new Vector2D(0.8, 0.02), new Vector2D(1.0, 0.11)))) - .addPlot(Constants.settings("Filters")) + .addTab(Constants.settings("Filters")) .addSeries(Constants.make("mouse y", IStream.create(plot::getMouseY))) .addSeries( Constants.make( @@ -94,7 +94,7 @@ public static void main(String[] args) throws InterruptedException { BStream.create(() -> plot.getMouseY() > 0.5) .filtered(new BDebounce.Both(1.0)))) - .addPlot(Constants.settings("XY Graph")) + .addTab(Constants.settings("XY Graph")) .addSeries(Constants.make("mouse position", VStream.create(plot::getMouse))) .addSeries(Constants.make( "jerk limit", diff --git a/src/com/stuypulse/stuylib/util/plot/Plot.java b/src/com/stuypulse/stuylib/util/plot/Plot.java index b6965c55..4920fdb9 100644 --- a/src/com/stuypulse/stuylib/util/plot/Plot.java +++ b/src/com/stuypulse/stuylib/util/plot/Plot.java @@ -67,7 +67,7 @@ public void build(String title, int width, int height) { mouse = new MouseTracker(frame); } - public Plot addPlot(Settings settings) { + public Plot addTab(Settings settings) { Tab tab = new Tab(settings); tabs.add(tab); From 1db1bd366d073759a3f6e18f8c37e34d659c6744 Mon Sep 17 00:00:00 2001 From: Sam Belliveau Date: Tue, 23 Aug 2022 12:41:13 -0400 Subject: [PATCH 10/10] Update build_release.yml --- .github/workflows/build_release.yml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/.github/workflows/build_release.yml b/.github/workflows/build_release.yml index 8bf82115..95847833 100644 --- a/.github/workflows/build_release.yml +++ b/.github/workflows/build_release.yml @@ -1,11 +1,7 @@ name: Build StuyLib -on: - push: - branches: [ main ] - pull_request: - branches: [ main ] +on: [push, fork, pull_request] jobs: build: