diff --git a/src/Model/Geometry/ProfileXYZ.py b/src/Model/Geometry/ProfileXYZ.py index 354be9162fda8df2f1788cb2420dde6e86d0572c..3d40fd69ac27f58e525e0d6e64ee6130876d68f5 100644 --- a/src/Model/Geometry/ProfileXYZ.py +++ b/src/Model/Geometry/ProfileXYZ.py @@ -489,46 +489,52 @@ class ProfileXYZ(Profile, SQLSubModel): # niveau d'eau pour lequel on a obtenu irg, ird, ptX et ptY # ==================================================================== - # initialisation - irg = -1 - ird = -1 + + # Get the index of last point with elevation lesser than water + # level (for the right and left river side) + i_left = -1 + i_right = -1 for i in range(self.number_points): if self.point(i).z <= z: - irg = i + i_left = i + break for i in reversed(range(self.number_points)): if self.point(i).z <= z: - ird = i + i_right = i + break - # interpolation des points ptX et ptY - if (irg < self.number_points - 1): + # Interpolate points at river left side + if (i_left > 0): x = np.interp( z, - [self.point(irg).z, self.point(irg + 1).z], - [self.point(irg).x, self.point(irg + 1).x] + [self.point(i_left).z, self.point(i_left - 1).z], + [self.point(i_left).x, self.point(i_left - 1).x] ) y = np.interp( z, - [self.point(irg).z, self.point(irg + 1).z], - [self.point(irg).y, self.point(irg + 1).y] + [self.point(i_left).z, self.point(i_left - 1).z], + [self.point(i_left).y, self.point(i_left - 1).y] ) - ptX = PointXYZ(x, y, z) + pt_left = PointXYZ(x, y, z) else: - ptX = self.point(0) - if (ird > 0): + pt_left = self.point(0) + + # Interpolate points at river right side + if (i_right < self.number_points - 1): x = np.interp( z, - [self.point(ird-1).z, self.point(ird).z], - [self.point(ird-1).x, self.point(ird).x] + [self.point(i_right).z, self.point(i_right + 1).z], + [self.point(i_right).x, self.point(i_right + 1).x] ) y = np.interp( z, - [self.point(ird).z, self.point(ird - 1).z], - [self.point(ird).y, self.point(ird - 1).y] + [self.point(i_right).z, self.point(i_right + 1).z], + [self.point(i_right).y, self.point(i_right + 1).y] ) - ptY = PointXYZ(x, y, z) + pt_right = PointXYZ(x, y, z) else: - ptY = self.point(self.number_points - 1) + pt_right = self.point(self.number_points - 1) - return ptX, ptY + return pt_left, pt_right diff --git a/src/Solver/Mage.py b/src/Solver/Mage.py index 83e6e5124040c41cc7f35edb2c6705133b80b4c3..dbd22a626c89cbf5ea78ecf8b49af51dd59585f0 100644 --- a/src/Solver/Mage.py +++ b/src/Solver/Mage.py @@ -1023,9 +1023,12 @@ class Mage8(Mage): reach.set(ri, timestamp, key, d) if key == "Z": profile = reach.profile(ri) - ptX, ptY = profile.geometry.get_water_limits(d) - reach.set(ri, timestamp, "ptX", ptX) - reach.set(ri, timestamp, "ptY", ptY) + limits = profile.geometry.get_water_limits(d) + reach.set( + ri, timestamp, + "water_limits", + limits + ) endline() end = newline().size <= 0 diff --git a/src/View/Results/PlotKPC.py b/src/View/Results/PlotKPC.py index 34a4ca5eb9b394b27873f68eed49130a401407ef..458e60485689e7ce7a6a275a44a01e1718e5e116 100644 --- a/src/View/Results/PlotKPC.py +++ b/src/View/Results/PlotKPC.py @@ -73,7 +73,6 @@ class PlotKPC(PamhyrPlot): reach = self.results.river.reach(self._current_reach_id) - self.draw_bottom(reach) self.draw_water_elevation(reach) self.draw_water_elevation_max(reach) diff --git a/src/View/Results/PlotXY.py b/src/View/Results/PlotXY.py index 72733c52cfe0e25763635cf0c3f0bc2a462bcf92..d74c1326403307230e01dc48fc3fe3577694ebcd 100644 --- a/src/View/Results/PlotXY.py +++ b/src/View/Results/PlotXY.py @@ -44,15 +44,20 @@ class PlotXY(PamhyrPlot): parent=parent ) - self.display_current = display_current - self.line_xy = [] self.line_gl = [] + self.overflow = [] - self._current_timestamp = max(results.get("timestamps")) + self._timestamps = results.get("timestamps") + self._current_timestamp = max(self._timestamps) self._current_reach_id = reach_id self._current_profile_id = profile_id + self.label_x = _translate("Results", "X (m)") + self.label_y = _translate("Results", "Y (m)") + + self._isometric_axis = True + @property def results(self): return self.data @@ -64,53 +69,41 @@ class PlotXY(PamhyrPlot): @timer def draw(self, highlight=None): - self.canvas.axes.cla() - self.canvas.axes.grid(color='grey', linestyle='--', linewidth=0.5) + self.init_axes() if self.results is None: return reach = self.results.river.reach(self._current_reach_id) + self.draw_profiles(reach) + self.draw_water_elevation(reach) + self.draw_water_elevation_max(reach) + self.draw_guide_lines(reach) + self.draw_current(reach) + + self.idle() + self._init = True + + def draw_profiles(self, reach): 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='black', fontsize=10 - ) - self.canvas.axes.set_ylabel( - _translate("Results", "Y (m)"), - color='black', fontsize=10 - ) - 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 'grey', - markersize=3, marker='+' + x, y, + color=self.color_plot_river_bottom, + **self.plot_default_kargs ) for x, y, kp in zip( reach.geometry.get_x(), reach.geometry.get_y(), - kp + reach.geometry.get_kp() ) ] - # Guide lines + def draw_guide_lines(self, reach): x_complete = reach.geometry.get_guidelines_x() y_complete = reach.geometry.get_guidelines_y() @@ -121,35 +114,106 @@ class PlotXY(PamhyrPlot): for x, y in zip(x_complete, y_complete) ] - if self.display_current: - # Current profile - profile = reach.profile(self._current_profile_id).geometry + def draw_current(self, reach): + profile = reach.profile(self._current_profile_id) + + self.plot_selected, = self.canvas.axes.plot( + profile.geometry.x(), + profile.geometry.y(), + color=self.color_plot, + **self.plot_default_kargs + ) + + + def draw_water_elevation_max(self, reach): + l_x, l_y, r_x, r_y = [], [], [], [] + overflow = [] - self.plot_selected, = self.canvas.axes.plot( - profile.x(), - profile.y(), - lw=1., markersize=3, - color="r", marker='+' + for profile in reach.profiles: + z_max = max(profile.get_key("Z")) + z_max_ts = 0 + for ts in self._timestamps: + z = profile.get_ts_key(ts, "Z") + if z == z_max: + z_max_ts = ts + break + + pt_left, pt_right = profile.get_ts_key(z_max_ts, "water_limits") + + l_x.append(pt_left.x) + l_y.append(pt_left.y) + r_x.append(pt_right.x) + r_y.append(pt_right.y) + + if self.is_overflow_point(profile, pt_left): + overflow.append(pt_left) + + if self.is_overflow_point(profile, pt_right): + overflow.append(pt_right) + + self.water_max_left = self.canvas.axes.plot( + l_x, l_y, + color=self.color_plot_river_water, + linestyle='dotted', + lw=1., + ) + + self.water_max_right = self.canvas.axes.plot( + r_x, r_y, + color=self.color_plot_river_water, + linestyle='dotted', + lw=1., + ) + + for p in overflow: + self.canvas.axes.plot( + p.x, p.y, + lw=1., + color=self.color_plot, + markersize=3, + marker='x' + ) + + + def is_overflow_point(self, profile, point): + left_limit = profile.geometry.point(0) + right_limit = profile.geometry.point( + profile.geometry.number_points - 1 + ) + + return ( + point == left_limit + or point == right_limit + ) + + + def draw_water_elevation(self, reach): + reach = self.results.river.reach(self._current_reach_id) + poly_l_x, poly_l_y, poly_r_x, poly_r_y = [], [], [], [] + + for profile in reach.profiles: + water_z = profile.get_ts_key( + self._current_timestamp, "Z" + ) + pt_left, pt_right = profile.get_ts_key( + self._current_timestamp, + "water_limits" ) - self.plot_selected.set_visible(True) - poly_x = [0] - poly_y = [0] + poly_l_x.append(pt_left.x) + poly_l_y.append(pt_left.y) + poly_r_x.append(pt_right.x) + poly_r_y.append(pt_right.y) - self.fill = self.canvas.axes.fill( + poly_x = poly_l_x + list(reversed(poly_r_x)) + poly_y = poly_l_y + list(reversed(poly_r_y)) + + self.water_fill = self.canvas.axes.fill( poly_x, poly_y, - color='skyblue', + color=self.color_plot_river_water_zone, alpha=0.7 ) - # 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() - self.update() - def set_reach(self, reach_id): self._current_reach_id = reach_id self._current_profile_id = 0 @@ -158,63 +222,91 @@ class PlotXY(PamhyrPlot): def set_profile(self, profile_id): self._current_profile_id = profile_id self.update_profile() + self.update_idle() def set_timestamp(self, timestamp): self._current_timestamp = timestamp - self.update_poly() + self.update() - def update_profile(self): + def update(self): + if not self._init: + self.draw() - reach = self.results.river.reach(self._current_reach_id) - if self.display_current: - # Current profile - profile = reach.profile(self._current_profile_id).geometry + self.update_water_elevation() + self.update_water_elevation_overflow() + + self.update_idle() - self.plot_selected.set_data(profile.x(), profile.y()) - self.plot_selected.set_visible(True) - self.canvas.draw_idle() + def update_profile(self): + reach = self.results.river.reach(self._current_reach_id) + profile = reach.profile(self._current_profile_id) - def update_poly(self): + self.plot_selected.set_data( + profile.geometry.x(), + profile.geometry.y() + ) + def update_water_elevation(self): reach = self.results.river.reach(self._current_reach_id) - profile = reach.profile(self._current_profile_id).geometry + poly_l_x, poly_l_y, poly_r_x, poly_r_y = [], [], [], [] - # Display water - poly_l_x = [] - poly_l_y = [] - poly_r_x = [] - poly_r_y = [] for profile in reach.profiles: water_z = profile.get_ts_key( self._current_timestamp, "Z" ) - ptX = profile.get_ts_key( - self._current_timestamp, "ptX" - ) - ptY = profile.get_ts_key( - self._current_timestamp, "ptY" + pt_left, pt_right = profile.get_ts_key( + self._current_timestamp, + "water_limits" ) - poly_l_x.append(ptX.x) - poly_l_y.append(ptX.y) - poly_r_x.append(ptY.x) - poly_r_y.append(ptY.y) - - # self.canvas.axes.plot( - # x, y, lw=1., - # color='b', - # markersize=1, - # marker='o' - # ) + poly_l_x.append(pt_left.x) + poly_l_y.append(pt_left.y) + poly_r_x.append(pt_right.x) + poly_r_y.append(pt_right.y) poly_x = poly_l_x + list(reversed(poly_r_x)) poly_y = poly_l_y + list(reversed(poly_r_y)) + poly = [] for i in range(len(poly_x)): poly.append([poly_x[i], poly_y[i]]) - self.fill[0].set_xy(poly) - self.canvas.draw_idle() - def update(self): - self.update_profile() - self.update_poly() + self.water_fill[0].set_xy(poly) + + def update_water_elevation_overflow(self): + reach = self.results.river.reach(self._current_reach_id) + profile = reach.profile(self._current_profile_id) + + overflow = [] + + for profile in reach.profiles: + pt_left, pt_right = profile.get_ts_key( + self._current_timestamp, + "water_limits" + ) + + left_limit = profile.geometry.point(0) + right_limit = profile.geometry.point( + profile.geometry.number_points - 1 + ) + + if pt_left == left_limit: + overflow.append(pt_left) + + if pt_right == right_limit: + overflow.append(pt_right) + + for plot in self.overflow: + plot[0].remove() + del plot[0] + self.overflow = [] + + for p in overflow: + plot = self.canvas.axes.plot( + p.x, p.y, + lw=1., + color=self.color_plot, + markersize=3, + marker='o' + ) + self.overflow.append(plot)