From d77b824cf7ab061072989aa8b70283efb5cb336c Mon Sep 17 00:00:00 2001
From: tobiglaser <76131623+tobiglaser@users.noreply.github.com>
Date: Tue, 10 Jun 2025 22:35:38 +0200
Subject: [PATCH] added setAxisRange functionality

---
 examples/studiMain.cpp |  4 +++-
 include/cute.h         |  3 ++-
 src/chartMenu.cpp      |  2 +-
 src/chartMenu.h        |  2 +-
 src/control.cpp        | 39 +++++++++++++++++++++++++++++++++++++--
 src/control.h          | 12 +++++++++++-
 src/cute.cpp           |  8 ++++++--
 src/cuteControl.h      |  9 +++++++--
 8 files changed, 68 insertions(+), 11 deletions(-)

diff --git a/examples/studiMain.cpp b/examples/studiMain.cpp
index 9040968..6e8bf3f 100644
--- a/examples/studiMain.cpp
+++ b/examples/studiMain.cpp
@@ -37,6 +37,7 @@ void setup()
 
 void superDummy()
 {
+    cute::setAxisRange(0, 0, 42, 0, 69);
     int prog = 0;
     while (cute::ok())
     {
@@ -92,7 +93,8 @@ std::string point2str(cute::Point p)
 void advancedDummy()
 {
     cute::resetPlot(0);
-    cute::setPlotScale(0, cute::logarithmic, cute::logarithmic);
+    //cute::setPlotScale(0, cute::logarithmic, cute::logarithmic);
+    cute::setAxisRange(0, -100, 200, -100, 200);
     std::vector<float> problem1D = cute::getProblemData1D();
     cute::logMessage(fvec2str(problem1D));
     cute::setPlotTheme(problem1D.size() - 1);
diff --git a/include/cute.h b/include/cute.h
index 64151fd..f66ca6a 100644
--- a/include/cute.h
+++ b/include/cute.h
@@ -112,6 +112,7 @@ namespace cute
     void DYNAMIC setLegendVisible(int plot, bool visible = true);
     void DYNAMIC setAxisTitles(int plot, const std::string& x, const std::string& y);
     void DYNAMIC setAxisVisible(int plot, bool x, bool y);
+    void DYNAMIC setAxisRange(int plot, float x_min, float x_max, float y_min, float y_max);
 
     void DYNAMIC registerAlgorithm(void (*func)(), const std::string& name, void (*localSetup)() = nullptr);
 
@@ -128,7 +129,7 @@ namespace cute
                            bool                      loop       = false,
                            const PlotProperties&     properties = {});
     void DYNAMIC undo(int plot);
-    void DYNAMIC resetPlot(int plot);
+    void DYNAMIC resetPlot(int plot, bool keepRanges = false);
 
     void DYNAMIC logMessage(const std::string& message);
     void DYNAMIC setStatusMessage(const std::string& message, int duration_s = 5);
diff --git a/src/chartMenu.cpp b/src/chartMenu.cpp
index 88e5f82..4846bd6 100644
--- a/src/chartMenu.cpp
+++ b/src/chartMenu.cpp
@@ -156,7 +156,7 @@ void ChartMenu::onReset()
                 // modal execution
                 int result = dialog.exec();
                 if (result == QDialog::Accepted)
-                    emit s_resetPlot(i);
+                    emit s_resetPlot(i, true);
             }
         }
     }
diff --git a/src/chartMenu.h b/src/chartMenu.h
index 8f1ffce..f095623 100644
--- a/src/chartMenu.h
+++ b/src/chartMenu.h
@@ -48,7 +48,7 @@ public slots:
 
 signals:
     void s_setPlotScale(int plot, int x, int y);
-    void s_resetPlot(int plot);
+    void s_resetPlot(int plot, bool keepRanges);
 };
 
 
diff --git a/src/control.cpp b/src/control.cpp
index 9dc3d59..81ab09d 100644
--- a/src/control.cpp
+++ b/src/control.cpp
@@ -38,6 +38,7 @@ void Control::makeConnections()
     connect(cc, &CuteControl::s_setPlotTheme, this, &Control::setPlotTheme);
     connect(cc, &CuteControl::s_setLegendVisible, this, &Control::setLegendVisible);
     connect(cc, &CuteControl::s_setAxisVisible, this, &Control::setAxisVisible);
+    connect(cc, &CuteControl::s_setAxisRange, this, &Control::setAxisRange);
     connect(cc, &CuteControl::s_setAxisTitles, this, &Control::setAxisTitles);
     connect(cc, &CuteControl::s_enableAutorun, this, &Control::enableAutorun);
     connect(cc, &CuteControl::s_setProblemSize, this, &Control::setProblemSize);
@@ -116,6 +117,7 @@ void Control::addPlot(int type)
 {
     onTopSeries.emplace_back();
     plotHistory.emplace_back();
+    axisRanges.emplace_back();
     if (type == cute::PlotType::chart)
     {
         addChart();
@@ -532,7 +534,7 @@ void Control::onPreviewButton()
             auto ptr = dynamic_cast<QtCharts::QChartView*>(w->graphingWidgets[i]);
             if (ptr)
             {
-                resetPlot(i);
+                resetPlot(i, true);
                 problemPreviewed = false;
                 CuteControl::get().plotPoints(getProblem(), i, {});
                 problemPreviewed = true;
@@ -723,6 +725,24 @@ void Control::resizeAxes(int plot)
         return;
     QChart* chart = chartView->chart();
 
+    if (axisRanges[plot].set)
+    {
+        QList<QAbstractAxis*> axes = chart->axes();
+        AxisRanges&           r    = axisRanges[plot];
+        for (auto axis : axes)
+        {
+            if (axis->orientation() == Qt::Orientation::Horizontal)
+            {
+                axis->setRange(r.x_min, r.x_max);
+            }
+            else
+            {
+                axis->setRange(r.y_min, r.y_max);
+            }
+        }
+        return;
+    }
+
     double maxX   = std::numeric_limits<double>::min();
     double maxY   = std::numeric_limits<double>::min();
     double minX   = std::numeric_limits<double>::max();
@@ -814,7 +834,7 @@ void Control::resizeAxes(int plot)
  * This currently only works with QCharts.
  * @param plot The plot to be reset.
  */
-void Control::resetPlot(int plot)
+void Control::resetPlot(int plot, bool keepRanges)
 {
     using namespace QtCharts;
     if (plot < (int)w->graphingWidgets.size() && plot >= 0)
@@ -826,6 +846,8 @@ void Control::resetPlot(int plot)
         }
         plotHistory[plot].clear();
         onTopSeries[plot].clear();
+        if (!keepRanges)
+            axisRanges[plot] = AxisRanges();
     }
 }
 
@@ -975,3 +997,16 @@ void Control::saveProblem()
             setStatusMessage("Error writing File " + path, 5000);
     }
 }
+
+void Control::setAxisRange(int plot, float x_min, float x_max, float y_min, float y_max)
+{
+    if (plot < (int)w->graphingWidgets.size() && plot >= 0)
+    {
+        axisRanges[plot].x_min = x_min;
+        axisRanges[plot].x_max = x_max;
+        axisRanges[plot].y_min = y_min;
+        axisRanges[plot].y_max = y_max;
+        axisRanges[plot].set   = x_min != x_max && y_min != y_max;
+        resizeAxes(plot);
+    }
+}
diff --git a/src/control.h b/src/control.h
index c40ae68..0b2aed8 100644
--- a/src/control.h
+++ b/src/control.h
@@ -13,6 +13,14 @@ class Control : public QObject
 {
     Q_OBJECT
 private:
+    struct AxisRanges
+    {
+        float x_min = 0;
+        float x_max = 0;
+        float y_min = 0;
+        float y_max = 0;
+        bool  set   = false;
+    };
     struct Algorithm
     {
         void (*algorithm)();
@@ -38,6 +46,7 @@ private:
     std::vector<cute::Point>                             getProblem();
     void                                                 resizeAxes(int plot);
     std::vector<std::vector<QtCharts::QAbstractSeries*>> onTopSeries;
+    std::vector<AxisRanges>                              axisRanges;
     void                                                 redrawOnTopSeries(int plot);
 
     std::vector<std::vector<std::variant<QtCharts::QAbstractSeries*, QGraphicsItem*>>> plotHistory;
@@ -65,6 +74,7 @@ public slots:
     void setLegendVisible(int plot, bool visible);
     void setAxisTitles(int plot, QString x, QString y);
     void setAxisVisible(int plot, bool x, bool y);
+    void setAxisRange(int plot, float x_min, float x_max, float y_min, float y_max);
     void onRunButton();
     void onSetupButton();
     void onAlgoSelected(int index);
@@ -75,7 +85,7 @@ public slots:
     void plotXYSeries(QtCharts::QXYSeries* s, int plot, bool onTop, bool legend, QString tooltip = "");
     void plotBarSeries(QtCharts::QBarSeries* series, int plot, bool onTop, bool legend);
     void highlightValue(float value, int plot, QColor c);
-    void resetPlot(int plot);
+    void resetPlot(int plot, bool keepRanges);
     void undo(int plot);
     void saveProblem();
     void addPlot(int type);
diff --git a/src/cute.cpp b/src/cute.cpp
index 084eb18..d188170 100644
--- a/src/cute.cpp
+++ b/src/cute.cpp
@@ -138,6 +138,10 @@ void cute::setAxisVisible(int plot, bool x, bool y)
     CuteControl::get().setAxisVisible(plot, x, y);
 }
 
+void cute::setAxisRange(int plot, float x_min, float x_max, float y_min, float y_max)
+{
+    CuteControl::get().setAxisRange(plot, x_min, x_max, y_min, y_max);
+}
 
 void cute::registerAlgorithm(void (*func)(), const std::string& name, void (*localSetup)())
 {
@@ -201,10 +205,10 @@ void cute::undo(int plot)
     timerResumeInternal();
 }
 
-void cute::resetPlot(int plot)
+void cute::resetPlot(int plot, bool keepRanges)
 {
     timerPauseInternal();
-    CuteControl::get().resetPlot(plot);
+    CuteControl::get().resetPlot(plot, keepRanges);
     timerResumeInternal();
 }
 
diff --git a/src/cuteControl.h b/src/cuteControl.h
index d9a3169..48fcbf6 100644
--- a/src/cuteControl.h
+++ b/src/cuteControl.h
@@ -39,10 +39,11 @@ signals:
     void s_setLegendVisible(int plot, bool visible);
     void s_setAxisTitles(int plot, QString x, QString y);
     void s_setAxisVisible(int plot, bool x, bool y);
+    void s_setAxisRange(int plot, float x_min, float x_max, float y_min, float y_max);
     void s_plotXYSeries(QtCharts::QXYSeries* series, int plot, bool onTop, bool legend, QString tooltip = "");
     void s_plotBarSeries(QtCharts::QBarSeries* series, int plot, bool onTop, bool legend);
     void s_highlightValue(float value, int plot, QColor c);
-    void s_resetPlot(int plot);
+    void s_resetPlot(int plot, bool keepRanges);
     void s_undo(int plot);
     void s_verbosityChanged(int level);
 
@@ -86,6 +87,10 @@ public:
 
     void setPlotVisible(int plot, bool visible) { emit s_setPlotVisible(plot, visible); }
 
+    void setAxisRange(int plot, float x_min, float x_max, float y_min, float y_max) {
+        emit s_setAxisRange(plot, x_min, x_max, y_min, y_max);
+    }
+
     void enableAutorun(bool run) { emit s_enableAutorun(run); }
 
     void setProblemSize(int n) { emit s_setProblemSize(n); }
@@ -230,7 +235,7 @@ public:
         emit s_plotXYSeries(s, plot, properties.onTop, legend);
     }
 
-    void resetPlot(int plot) { emit s_resetPlot(plot); }
+    void resetPlot(int plot, bool keepRanges) { emit s_resetPlot(plot, keepRanges); }
     void undo(int plot) { emit s_undo(plot); }
     void setPlotScale(int plot, cute::Scale x, cute::Scale y) { emit s_setPlotScale(plot, (int)x, (int)y); }
     void setLegendVisible(int plot, bool visible) { emit s_setLegendVisible(plot, visible); }
-- 
GitLab