From 2faab43aed65332040ab53666bac0c5c47f95c65 Mon Sep 17 00:00:00 2001
From: Pierre-Antoine Rouby <pierre-antoine.rouby@inrae.fr>
Date: Wed, 9 Aug 2023 10:36:57 +0200
Subject: [PATCH] Results: Add XY plot (without water zone)

---
 src/Model/Results/River/River.py |   8 ++
 src/View/Results/PlotXY.py       | 121 +++++++++++++++++++++++++++++++
 src/View/Results/Window.py       |  18 +++--
 3 files changed, 139 insertions(+), 8 deletions(-)

diff --git a/src/Model/Results/River/River.py b/src/Model/Results/River/River.py
index 22312a9a..ae8b33c0 100644
--- a/src/Model/Results/River/River.py
+++ b/src/Model/Results/River/River.py
@@ -34,6 +34,10 @@ class Profile(object):
     def kp(self):
         return self._profile.kp
 
+    @property
+    def geometry(self):
+        return self._profile
+
     def set(self, timestamp, key, data):
         if timestamp not in self._data:
             self._data[timestamp] = {}
@@ -66,6 +70,10 @@ class Reach(object):
     def name(self):
         return self._reach.name
 
+    @property
+    def geometry(self):
+        return self._reach
+
     @property
     def profiles(self):
         return self._profiles.copy()
diff --git a/src/View/Results/PlotXY.py b/src/View/Results/PlotXY.py
index a8c4b206..43934073 100644
--- a/src/View/Results/PlotXY.py
+++ b/src/View/Results/PlotXY.py
@@ -15,3 +15,124 @@
 # along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 # -*- coding: utf-8 -*-
+
+from tools import timer, trace
+from View.Plot.APlot import APlot
+
+from PyQt5.QtCore import (
+    QCoreApplication
+)
+
+_translate = QCoreApplication.translate
+
+class PlotXY(APlot):
+    def __init__(self, canvas=None, results=None,
+                 reach_id=0, profile_id=0,
+                 toolbar=None, display_current=True):
+        super(PlotXY, self).__init__(
+            canvas=canvas,
+            data=results,
+            toolbar=toolbar
+        )
+
+        self.display_current = display_current
+
+        self.line_xy = []
+        self.line_gl = []
+
+        self._current_reach_id = reach_id
+        self._current_profile_id = profile_id
+
+    @property
+    def results(self):
+        return self.data
+
+    @timer
+    def draw(self, highlight=None):
+        self.canvas.axes.cla()
+        self.canvas.axes.grid(color='grey', linestyle='--', linewidth=0.5)
+
+        if self.results is None:
+            return
+
+        reach = self.results.river.reach(self._current_reach_id)
+
+        if reach.geometry.number_profiles == 0:
+            self._init = False
+            return
+
+        kp_min, kp_max = (-1, -1)
+        if highlight is not None:
+            kp_min, kp_max = highlight
+
+        # Axes
+        self.canvas.axes.set_xlabel(
+            _translate("Results", "X (m)"),
+            color='green', fontsize=12
+        )
+        self.canvas.axes.set_ylabel(
+            _translate("Results", "Y (m)"),
+            color='green', fontsize=12
+        )
+        self.canvas.axes.axis("equal")
+
+        kp = reach.geometry.get_kp()
+        self.canvas.axes.set_xlim(
+            left = min(kp), right = max(kp)
+        )
+
+        # Draw line for each profile
+        self.line_xy = [
+            self.canvas.axes.plot(
+                x, y, lw=1.,
+                color='b' if kp_min <= kp <= kp_max else 'r',
+                markersize=3, marker='+'
+            )
+            for x, y, kp in zip(
+                    reach.geometry.get_x(),
+                    reach.geometry.get_y(),
+                    kp
+            )
+        ]
+
+        # Guide lines
+        x_complete = reach.geometry.get_guidelines_x()
+        y_complete = reach.geometry.get_guidelines_y()
+
+        self.line_gl = [
+            self.canvas.axes.plot(
+                x, y,
+            )
+            for x, y in zip(x_complete, y_complete)
+        ]
+
+        if self.display_current:
+            # Current profile
+            profile = reach.geometry.profile(self._current_profile_id)
+
+            self.plot_selected, = self.canvas.axes.plot(
+                profile.x(),
+                profile.y(),
+                lw=1., markersize=3,
+                marker='+', color="b"
+            )
+            self.plot_selected.set_visible(False)
+
+        self.canvas.axes.autoscale_view(True, True, True)
+        self.canvas.axes.autoscale()
+        self.canvas.figure.tight_layout()
+        self.canvas.figure.canvas.draw_idle()
+        if self.toolbar is not None:
+            self.toolbar.update()
+
+    def set_reach(self, reach_id):
+        self._current_reach_id = reach_id
+        self._current_profile_id = 0
+        self.draw()
+
+    def set_profile(self, profile_id):
+        self._current_profile_id = profile_id
+        self.draw()
+
+    def update(self):
+        self.draw()
diff --git a/src/View/Results/Window.py b/src/View/Results/Window.py
index e4c1b65c..e2d3f8b3 100644
--- a/src/View/Results/Window.py
+++ b/src/View/Results/Window.py
@@ -40,8 +40,8 @@ from PyQt5.QtWidgets import (
 )
 
 from View.Plot.MplCanvas import MplCanvas
-from View.Geometry.PlotKPC import PlotKPC
 
+from View.Results.PlotXY import PlotXY
 from View.Results.Table import TableModel
 from View.Results.translate import *
 from View.Stricklers.Window import StricklersWindow
@@ -110,13 +110,15 @@ class ResultsWindow(ASubMainWindow, ListedSubWindow):
         self.plot_layout = self.find(QVBoxLayout, "verticalLayout")
         self.plot_layout.addWidget(self.canvas)
 
-        # self.plot = PlotKPC(
-        #     canvas = self.canvas,
-        #     data = self._reach.reach,
-        #     toolbar = None,
-        #     display_current = False
-        # )
-        # self.plot.draw()
+        self.plot_xy = PlotXY(
+            canvas = self.canvas,
+            results = self._results,
+            reach_id = 0,
+            profile_id = 0,
+            toolbar = None,
+            display_current = False
+        )
+        self.plot_xy.draw()
 
         self.canvas_2 = MplCanvas(width=5, height=4, dpi=100)
         self.canvas_2.setObjectName("canvas_2")
-- 
GitLab