From 3693c32d4bdbd2f07cbc400777688c7c03a0d363 Mon Sep 17 00:00:00 2001 From: Theophile Terraz <theophile.terraz@inrae.fr> Date: Wed, 7 Aug 2024 17:49:52 +0200 Subject: [PATCH] auto BC generation --- .../BoundaryCondition/BoundaryCondition.py | 12 +++++ src/Model/Geometry/ProfileXYZ.py | 7 ++- src/View/BoundaryCondition/Edit/Table.py | 12 +++++ .../BoundaryCondition/Edit/UndoCommand.py | 26 +++++++++++ src/View/BoundaryCondition/Edit/Window.py | 45 +++++++++++++++++++ src/View/ui/EditBoundaryConditions.ui | 21 +++++++++ 6 files changed, 119 insertions(+), 4 deletions(-) diff --git a/src/Model/BoundaryCondition/BoundaryCondition.py b/src/Model/BoundaryCondition/BoundaryCondition.py index eddc52b1..265e8b2f 100644 --- a/src/Model/BoundaryCondition/BoundaryCondition.py +++ b/src/Model/BoundaryCondition/BoundaryCondition.py @@ -371,3 +371,15 @@ class BoundaryCondition(SQLSubModel): d = self._data d[index], d[prev] = d[prev], d[index] self._status.modified() + + def reach(self, river): + edges = [] + if self._node != None: + if river != None: + for edge in river.edges(): + if edge.node1.name == self._node.name: + edges.append(edge.reach) + if edge.node2.name == self._node.name: + edges.append(edge.reach) + + return edges diff --git a/src/Model/Geometry/ProfileXYZ.py b/src/Model/Geometry/ProfileXYZ.py index 0e29c8c3..911ae890 100644 --- a/src/Model/Geometry/ProfileXYZ.py +++ b/src/Model/Geometry/ProfileXYZ.py @@ -436,8 +436,6 @@ class ProfileXYZ(Profile, SQLSubModel): area += poly.area return area - return poly.area - def wet_radius(self, z): p = self.wet_perimeter(z) a = self.wet_area(z) @@ -482,14 +480,15 @@ class ProfileXYZ(Profile, SQLSubModel): if zz[i] < z: line.append([station[i], zz[i]]) - if zz[i] <= z and zz[i+1] > z: + if zz[i] <= z and zz[i+1] >= z: y = np.interp( z, [zz[i], zz[i+1]], [station[i], station[i+1]] ) line.append([y, z]) - lines.append(geometry.LineString(line)) + if len(line) > 2: + lines.append(geometry.LineString(line)) line = [] return lines diff --git a/src/View/BoundaryCondition/Edit/Table.py b/src/View/BoundaryCondition/Edit/Table.py index d4a9f8a6..c5f268a7 100644 --- a/src/View/BoundaryCondition/Edit/Table.py +++ b/src/View/BoundaryCondition/Edit/Table.py @@ -48,6 +48,7 @@ from Model.BoundaryCondition.BoundaryConditionTypes import ( from View.BoundaryCondition.Edit.UndoCommand import ( SetDataCommand, AddCommand, DelCommand, SortCommand, MoveCommand, PasteCommand, + ReplaceDataCommand, ) _translate = QCoreApplication.translate @@ -200,3 +201,14 @@ class TableModel(PamhyrTableModel): def update(self): # self.auto_sort() self.layoutChanged.emit() + + def replace_data(self, data1, data2): + self.layoutAboutToBeChanged.emit() + self._undo.push( + ReplaceDataCommand( + self._data, data1, data2 + ) + ) + self.layoutAboutToBeChanged.emit() + self.update() + diff --git a/src/View/BoundaryCondition/Edit/UndoCommand.py b/src/View/BoundaryCondition/Edit/UndoCommand.py index 02e0a48e..d7ef2671 100644 --- a/src/View/BoundaryCondition/Edit/UndoCommand.py +++ b/src/View/BoundaryCondition/Edit/UndoCommand.py @@ -181,3 +181,29 @@ class PasteCommand(QUndoCommand): def redo(self): for bc in self._bcs: self._data.insert(self._row, bc) + +class ReplaceDataCommand(QUndoCommand): + def __init__(self, data, data1, data2): + QUndoCommand.__init__(self) + self._data = data + self._old_rows = len(data) + self._data1 = data1 + self._data2 = data2 + self._rows = len(data1) + + self._old_bc = [] + for row in range(self._old_rows): + self._old_bc.append((row, self._data.get_i(row))) + self._old_bc.sort() + + def undo(self): + self._data.delete_i(list(range(self._rows))) + for row, el in self._old_bc: + self._data.insert(row, el) + + def redo(self): + self._data.delete_i(list(range(self._old_rows))) + for row in range(self._rows): + self._data.add(row) + self._data._set_i_c_v(row, 0, self._data1[row]) + self._data._set_i_c_v(row, 1, self._data2[row]) diff --git a/src/View/BoundaryCondition/Edit/Window.py b/src/View/BoundaryCondition/Edit/Window.py index 94557ddd..e6b53f23 100644 --- a/src/View/BoundaryCondition/Edit/Window.py +++ b/src/View/BoundaryCondition/Edit/Window.py @@ -20,6 +20,8 @@ import logging from tools import timer, trace +from numpy import sqrt + from View.Tools.PamhyrWindow import PamhyrWindow from View.Tools.PamhyrWidget import PamhyrWidget from View.Tools.PamhyrDelegate import PamhyrExTimeDelegate @@ -104,6 +106,7 @@ class EditBoundaryConditionWindow(PamhyrWindow): self._data = data trad = BCETranslate() self._long_types = trad.get_dict("long_types") + self._study = study name = trad[self._pamhyr_name] if self._data is not None: @@ -193,6 +196,14 @@ class EditBoundaryConditionWindow(PamhyrWindow): self.find(QAction, "action_add").triggered.connect(self.add) self.find(QAction, "action_del").triggered.connect(self.delete) self.find(QAction, "action_sort").triggered.connect(self.sort) + self.find(QAction, "action_generate_uniform").triggered.connect(self.generate_uniform) + self.find(QAction, "action_generate_critical").triggered.connect(self.generate_critical) + if self._data.bctype != "ZD" or not self._data.has_node: + self.find(QAction, "action_generate_uniform").setVisible(False) + self.find(QAction, "action_generate_critical").setVisible(False) + else: + self.find(QAction, "action_generate_uniform").setVisible(True) + self.find(QAction, "action_generate_critical").setVisible(True) self._table.dataChanged.connect(self.update) self._table.layoutChanged.connect(self.update) @@ -311,3 +322,37 @@ class EditBoundaryConditionWindow(PamhyrWindow): self._table.redo() self.plot.update() self.widget_update() + + def generate_uniform(self): + if self._data.has_node: + node = self._data.node + reach = self._data.reach(self._study.river)[0] + profile = reach.profiles[-1] + incline = reach.get_incline_median_mean() + z_min = profile.z_min() + z_max = profile.z_max() + strickler = 25 + height = [(i)*(z_max-z_min)/50 for i in range(51)] + q = [((profile.wet_width(z_min + h) * 0.8) * strickler + * (h ** (5/3)) + * (abs(incline) ** (0.5))) + for h in height + ] + self._table.replace_data(height, q) + + return + + def generate_critical(self): + if self._data.has_node: + node = self._data.node + reach = self._data.reach(self._study.river)[0] + profile = reach.profiles[-1] + incline = reach.get_incline_median_mean() + z_min = profile.z_min() + z_max = profile.z_max() + height = [(i)*(z_max-z_min)/50 for i in range(51)] + q = [sqrt(9.81 * (profile.wet_area(z_min + h) ** 3) / profile.wet_width(z_min + h)) + for h in height + ] + self._table.replace_data(height, q) + return diff --git a/src/View/ui/EditBoundaryConditions.ui b/src/View/ui/EditBoundaryConditions.ui index b27232d2..c2c81378 100644 --- a/src/View/ui/EditBoundaryConditions.ui +++ b/src/View/ui/EditBoundaryConditions.ui @@ -73,6 +73,8 @@ <addaction name="action_add"/> <addaction name="action_del"/> <addaction name="action_sort"/> + <addaction name="action_generate_uniform"/> + <addaction name="action_generate_critical"/> </widget> <action name="action_add"> <property name="checkable"> @@ -119,6 +121,25 @@ <string>Sort points</string> </property> </action> + <action name="action_generate_uniform"> + <property name="text"> + <string>Generate uniform</string> + </property> + <property name="iconText"> + <string>Generate uniform</string> + </property> + <property name="toolTip"> + <string>Generate rating curve from Manning law</string> + </property> + </action> + <action name="action_generate_critical"> + <property name="text"> + <string>Generate critical</string> + </property> + <property name="toolTip"> + <string>Generate rating curve as Q(z) = Sqrt(g*S(z)^3/L(z))</string> + </property> + </action> </widget> <resources/> <connections/> -- GitLab