mirror of https://gitlab.com/pamhyr/pamhyr2
Scenarios: Merge remote-tracking branch 'origin/master'.
commit
e43c20c1e6
|
|
@ -1334,7 +1334,7 @@ https://gitlab.irstea.fr/theophile.terraz/pamhyr
|
|||
|
||||
You can improve or add translation for the project. To contribute to
|
||||
Pamhyr2 translate, you need to use Qt Linguist[fn:qt-linguist]. Open
|
||||
Qt-linguist and edite the translation ({{{file(.ts)}}}) file, finally,
|
||||
Qt-linguist and edit the translation ({{{file(.ts)}}}) file, finally,
|
||||
commit the new version of file and make a merge request.
|
||||
|
||||
If you want add a new language, edit the script
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -411,7 +411,7 @@ class MeshingWithMageMailleurTT(AMeshingTool):
|
|||
str,
|
||||
[
|
||||
st_file, m_file,
|
||||
"update_rk", step,
|
||||
"update_kp", step,
|
||||
limites[0], limites[1],
|
||||
directrices[0], directrices[1],
|
||||
orientation, lm, linear, origin, origin_value
|
||||
|
|
|
|||
|
|
@ -509,3 +509,15 @@ class BoundaryCondition(SQLSubModel):
|
|||
d = self._data
|
||||
d[index], d[prev] = d[prev], d[index]
|
||||
self._status.modified()
|
||||
|
||||
def reach(self, river):
|
||||
r = []
|
||||
if self._node is not None:
|
||||
if river is not None:
|
||||
for edge in river.edges():
|
||||
if edge.node1.name == self._node.name:
|
||||
r.append(edge.reach)
|
||||
if edge.node2.name == self._node.name:
|
||||
r.append(edge.reach)
|
||||
|
||||
return r
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@ from tools import trace, timer
|
|||
from Model.Tools.PamhyrDB import SQLSubModel
|
||||
from Model.Scenario import Scenario
|
||||
|
||||
from numpy import interp
|
||||
|
||||
logger = logging.getLogger()
|
||||
|
||||
|
||||
|
|
@ -290,3 +292,17 @@ class Friction(SQLSubModel):
|
|||
def end_strickler(self, strickler):
|
||||
self._end_strickler = strickler
|
||||
self._status.modified()
|
||||
|
||||
def get_friction(self, rk):
|
||||
if not self.contains_rk(rk):
|
||||
return None
|
||||
minor = interp(rk,
|
||||
[self.begin_rk, self.end_rk],
|
||||
[self.begin_strickler.minor,
|
||||
self.end_strickler.minor])
|
||||
medium = interp(rk,
|
||||
[self.begin_rk, self.end_rk],
|
||||
[self.begin_strickler.medium,
|
||||
self.end_strickler.medium])
|
||||
|
||||
return minor, medium
|
||||
|
|
|
|||
|
|
@ -332,8 +332,17 @@ class Profile(object):
|
|||
def wet_points(self, z):
|
||||
raise NotImplementedMethodeError(self, self.wet_point)
|
||||
|
||||
def wet_width(self, z):
|
||||
raise NotImplementedMethodeError(self, self.wet_width)
|
||||
|
||||
def wet_perimeter(self, z):
|
||||
raise NotImplementedMethodeError(self, self.wet_perimeter)
|
||||
|
||||
def wet_area(self, z):
|
||||
raise NotImplementedMethodeError(self, self.wet_area)
|
||||
|
||||
def wet_radius(self, z):
|
||||
raise NotImplementedMethodeError(self, self.wet_radius)
|
||||
|
||||
def get_nb_wet_areas(self, z):
|
||||
raise NotImplementedMethodeError(self, self.get_nb_wet_areas)
|
||||
|
|
|
|||
|
|
@ -486,31 +486,125 @@ class ProfileXYZ(Profile, SQLSubModel):
|
|||
|
||||
return abs(rg.dist(rd))
|
||||
|
||||
def wet_perimeter(self, z):
|
||||
poly = self.wet_polygon(z)
|
||||
def wet_width(self, z):
|
||||
start, end = self.get_all_water_limits_ac(z)
|
||||
|
||||
if poly is None:
|
||||
if len(start) == 0:
|
||||
return 0
|
||||
|
||||
return poly.length
|
||||
length = 0.0
|
||||
for s, e in zip(start, end):
|
||||
length += abs(s - e)
|
||||
return length
|
||||
|
||||
def wet_perimeter(self, z):
|
||||
lines = self.wet_lines(z)
|
||||
|
||||
if lines is None:
|
||||
return 0
|
||||
|
||||
length = 0.0
|
||||
for line in lines:
|
||||
length += line.length
|
||||
return length
|
||||
|
||||
def wet_area(self, z):
|
||||
poly = self.wet_polygon(z)
|
||||
lines = self.wet_lines(z)
|
||||
|
||||
if poly is None:
|
||||
if lines is None:
|
||||
return 0
|
||||
|
||||
return poly.area
|
||||
area = 0.0
|
||||
for line in lines:
|
||||
if len(line.coords) > 2:
|
||||
poly = geometry.Polygon(line)
|
||||
area += poly.area
|
||||
return area
|
||||
|
||||
def wet_radius(self, z):
|
||||
p = self.wet_perimeter(z)
|
||||
a = self.wet_area(z)
|
||||
|
||||
if p == 0:
|
||||
return 0
|
||||
|
||||
return a/p
|
||||
|
||||
def wet_line(self, z):
|
||||
points = self.wet_points(z)
|
||||
if len(points) < 3:
|
||||
return None
|
||||
|
||||
zz = map(lambda p: p.z, points)
|
||||
station = self._get_station(points)
|
||||
|
||||
line = geometry.LineString(list(zip(station, zz)))
|
||||
return line
|
||||
|
||||
def wet_lines(self, z):
|
||||
points = self._points
|
||||
if len(points) < 3:
|
||||
return None
|
||||
|
||||
lines = []
|
||||
|
||||
zz = list(map(lambda p: p.z, points))
|
||||
station = self._get_station(points)
|
||||
|
||||
line = []
|
||||
for i in range(self.number_points-1):
|
||||
|
||||
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])
|
||||
|
||||
if zz[i] < z:
|
||||
line.append([station[i], zz[i]])
|
||||
|
||||
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])
|
||||
if len(line) > 2:
|
||||
lines.append(geometry.LineString(line))
|
||||
line = []
|
||||
|
||||
if zz[self.number_points-1] < z:
|
||||
line.append([station[self.number_points-1], z])
|
||||
if len(line) > 2:
|
||||
lines.append(geometry.LineString(line))
|
||||
line = []
|
||||
|
||||
return lines
|
||||
|
||||
def max_water_depth(self, z):
|
||||
return z - self.z_min()
|
||||
|
||||
def mean_water_depth(self, z):
|
||||
a = self.wet_area(z)
|
||||
w = self.wet_width(z)
|
||||
|
||||
if w == 0:
|
||||
return 0
|
||||
|
||||
return a/w
|
||||
|
||||
def wet_polygon(self, z):
|
||||
points = self.wet_points(z)
|
||||
if len(points) < 3:
|
||||
return None
|
||||
|
||||
z = map(lambda p: p.z, points)
|
||||
zz = map(lambda p: p.z, points)
|
||||
station = self._get_station(points)
|
||||
|
||||
poly = geometry.Polygon(list(zip(station, z)))
|
||||
poly = geometry.Polygon(list(zip(station, zz)))
|
||||
return poly
|
||||
|
||||
def wet_points(self, z):
|
||||
|
|
@ -522,6 +616,63 @@ class ProfileXYZ(Profile, SQLSubModel):
|
|||
|
||||
return points
|
||||
|
||||
def get_nb_wet_areas(self, z):
|
||||
|
||||
n_zones = 0
|
||||
points = self._points
|
||||
if points[0].z <= z:
|
||||
n_zones += 1
|
||||
|
||||
for i in range(self.number_points-1):
|
||||
if points[i].z > z and points[i+1].z <= z:
|
||||
n_zones += 1
|
||||
|
||||
return n_zones
|
||||
|
||||
def get_all_water_limits_ac(self, z):
|
||||
"""
|
||||
Determine all water limits for z elevation.
|
||||
"""
|
||||
|
||||
points = self._points
|
||||
if len(points) < 3:
|
||||
return None
|
||||
|
||||
zz = list(map(lambda p: p.z, points))
|
||||
station = self._get_station(points)
|
||||
|
||||
start = []
|
||||
if points[0].z <= z:
|
||||
start.append(station[0])
|
||||
|
||||
for i in range(self.number_points-1):
|
||||
if zz[i] > z and zz[i+1] <= z:
|
||||
y = np.interp(
|
||||
z,
|
||||
[zz[i], zz[i+1]],
|
||||
[station[i], station[i+1]]
|
||||
)
|
||||
start.append(y)
|
||||
|
||||
end = []
|
||||
if points[-1].z <= z:
|
||||
end.append(station[-1])
|
||||
|
||||
for i in reversed(range(self.number_points-1)):
|
||||
if zz[i] <= z and zz[i+1] > z:
|
||||
y = np.interp(
|
||||
z,
|
||||
[zz[i], zz[i+1]],
|
||||
[station[i], station[i+1]]
|
||||
)
|
||||
end.append(y)
|
||||
|
||||
if len(start) != len(end):
|
||||
logger.error(f"ERROR in get_all_water_limits_ac")
|
||||
return [], []
|
||||
|
||||
return start, list(reversed(end))
|
||||
|
||||
def get_water_limits(self, z):
|
||||
"""
|
||||
Determine left and right limits of water elevation.
|
||||
|
|
@ -585,8 +736,8 @@ class ProfileXYZ(Profile, SQLSubModel):
|
|||
Returns:
|
||||
Projection of the points of the profile on a plane.
|
||||
"""
|
||||
if self.nb_points < 3:
|
||||
return None
|
||||
if self.nb_points < 2:
|
||||
return [0.0]
|
||||
else:
|
||||
return self._get_station(self.points)
|
||||
|
||||
|
|
@ -718,3 +869,9 @@ class ProfileXYZ(Profile, SQLSubModel):
|
|||
self.point(i),
|
||||
self.point(i+1)
|
||||
)
|
||||
|
||||
def shift(self, x, y, z):
|
||||
for p in self.points:
|
||||
p.x = p.x + x
|
||||
p.y = p.y + y
|
||||
p.z = p.z + z
|
||||
|
|
|
|||
|
|
@ -479,8 +479,14 @@ class InitialConditions(SQLSubModel):
|
|||
logger.debug(f"incline = {incline}")
|
||||
self._data = []
|
||||
for profile in profiles:
|
||||
width = profile.width_approximation()
|
||||
strickler = 25
|
||||
width = profile.wet_width(profile.z_min() + height)
|
||||
frictions = self._reach.frictions.frictions
|
||||
strickler = None
|
||||
for f in frictions:
|
||||
if f.contains_rk(profile.rk):
|
||||
strickler = f.get_friction(profile.rk)[0]
|
||||
if strickler is None:
|
||||
strickler = 25.0
|
||||
|
||||
if not compute_discharge:
|
||||
discharge = data_discharge[profile.rk]
|
||||
|
|
@ -533,7 +539,13 @@ class InitialConditions(SQLSubModel):
|
|||
self._data = []
|
||||
for profile in profiles:
|
||||
width = profile.width_approximation()
|
||||
strickler = 25
|
||||
frictions = self._reach.frictions.frictions
|
||||
strickler = None
|
||||
for f in frictions:
|
||||
if f.contains_rk(profile.rk):
|
||||
strickler = f.get_friction(profile.rk)[0]
|
||||
if strickler is None:
|
||||
strickler = 25.0
|
||||
|
||||
if not compute_height:
|
||||
height = data_height[profile.rk]
|
||||
|
|
|
|||
|
|
@ -324,7 +324,7 @@ class Mage(CommandLineSolver):
|
|||
if t in ["HYD", "QSO", "LIM"]:
|
||||
v0 /= 60 # Convert first column to minute
|
||||
|
||||
f.write(f"{v0:10}{v1:10}\n")
|
||||
f.write(f"{v0:9} {v1:9} \n")
|
||||
|
||||
return files
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,68 @@
|
|||
# GenerateDialog.py -- Pamhyr
|
||||
# Copyright (C) 2023-2024 INRAE
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from View.Tools.PamhyrWindow import PamhyrDialog
|
||||
|
||||
from PyQt5.QtGui import (
|
||||
QKeySequence,
|
||||
)
|
||||
|
||||
from PyQt5.QtCore import (
|
||||
Qt, QVariant, QAbstractTableModel,
|
||||
)
|
||||
|
||||
from PyQt5.QtWidgets import (
|
||||
QDialogButtonBox, QComboBox, QUndoStack, QShortcut,
|
||||
QDoubleSpinBox, QCheckBox, QPushButton
|
||||
)
|
||||
|
||||
|
||||
class GenerateDialog(PamhyrDialog):
|
||||
_pamhyr_ui = "BoundaryConditionsDialogGenerator"
|
||||
_pamhyr_name = "Boundary Condition Options"
|
||||
|
||||
def __init__(self,
|
||||
value,
|
||||
reach,
|
||||
title="Boundary Condition Options",
|
||||
trad=None,
|
||||
parent=None):
|
||||
super(GenerateDialog, self).__init__(
|
||||
title=trad[self._pamhyr_name],
|
||||
options=[],
|
||||
trad=trad,
|
||||
parent=parent
|
||||
)
|
||||
|
||||
self.value = value
|
||||
self.find(QDoubleSpinBox, "doubleSpinBox").setValue(self.value)
|
||||
self.reach = reach
|
||||
self.find(QPushButton, "EstimateButton").clicked.connect(
|
||||
self.estimate
|
||||
)
|
||||
|
||||
def accept(self):
|
||||
self.value = self.find(QDoubleSpinBox, "doubleSpinBox").value()
|
||||
super().accept()
|
||||
|
||||
def reject(self):
|
||||
self.close()
|
||||
|
||||
def estimate(self):
|
||||
self.value = abs(self.reach.get_incline_median_mean())
|
||||
self.find(QDoubleSpinBox, "doubleSpinBox").setValue(self.value)
|
||||
|
|
@ -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,13 @@ 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()
|
||||
|
|
|
|||
|
|
@ -181,3 +181,30 @@ 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])
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -48,6 +50,7 @@ from View.BoundaryCondition.Edit.translate import BCETranslate
|
|||
from View.BoundaryCondition.Edit.UndoCommand import SetMetaDataCommand
|
||||
from View.BoundaryCondition.Edit.Table import TableModel
|
||||
from View.BoundaryCondition.Edit.Plot import Plot
|
||||
from View.BoundaryCondition.Edit.GenerateDialog import GenerateDialog
|
||||
|
||||
_translate = QCoreApplication.translate
|
||||
|
||||
|
|
@ -104,6 +107,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:
|
||||
|
|
@ -200,6 +204,18 @@ class EditBoundaryConditionWindow(PamhyrWindow):
|
|||
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)
|
||||
|
||||
|
|
@ -320,3 +336,46 @@ 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 = abs(reach.get_incline_median_mean())
|
||||
dlg = GenerateDialog(incline,
|
||||
reach,
|
||||
trad=self._trad,
|
||||
parent=self)
|
||||
if dlg.exec():
|
||||
incline = dlg.value
|
||||
frictions = reach._parent.frictions.frictions
|
||||
z_min = profile.z_min()
|
||||
z_max = profile.z_max()
|
||||
strickler = None
|
||||
for f in frictions:
|
||||
if f.contains_rk(profile.rk):
|
||||
strickler = f.get_friction(profile.rk)[0]
|
||||
if strickler is None:
|
||||
strickler = 25.0
|
||||
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]
|
||||
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
|
||||
|
|
|
|||
|
|
@ -32,6 +32,8 @@ class BCETranslate(BCTranslate):
|
|||
self._dict["Edit Boundary Conditions"] = _translate(
|
||||
"BoundaryCondition", "Edit boundary conditions"
|
||||
)
|
||||
self._dict["Boundary Condition Options"] = _translate(
|
||||
"BoundaryCondition", "Boundary Condition Options")
|
||||
|
||||
self._sub_dict["table_headers"] = {
|
||||
"x": _translate("BoundaryCondition", "X"),
|
||||
|
|
|
|||
|
|
@ -313,10 +313,6 @@ class Plot(PamhyrPlot):
|
|||
x_carto = self.data.x()
|
||||
y_carto = self.data.y()
|
||||
|
||||
if (len(x_carto) < 3 or len(y_carto) < 3 or len(x) < 3):
|
||||
# Noting to do in this case
|
||||
return
|
||||
|
||||
self.profile_line2D, = self.canvas.axes.plot(
|
||||
x, y, color=self.color_plot,
|
||||
lw=1.5, markersize=7, marker='+',
|
||||
|
|
|
|||
|
|
@ -0,0 +1,60 @@
|
|||
# ShiftDialog.py -- Pamhyr
|
||||
# Copyright (C) 2023-2024 INRAE
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from View.Tools.PamhyrWindow import PamhyrDialog
|
||||
|
||||
|
||||
class ShiftDialog(PamhyrDialog):
|
||||
_pamhyr_ui = "GeometryReachShift"
|
||||
_pamhyr_name = "Shift"
|
||||
|
||||
def __init__(self, trad=None, parent=None):
|
||||
super(ShiftDialog, self).__init__(
|
||||
title=trad[self._pamhyr_name],
|
||||
trad=trad,
|
||||
options=[],
|
||||
parent=parent
|
||||
)
|
||||
|
||||
self._init_default_values()
|
||||
|
||||
def _init_default_values(self):
|
||||
self._dx = 0.0
|
||||
self._dy = 0.0
|
||||
self._dz = 0.0
|
||||
|
||||
@property
|
||||
def dx(self):
|
||||
return self._dx
|
||||
|
||||
@property
|
||||
def dy(self):
|
||||
return self._dy
|
||||
|
||||
@property
|
||||
def dz(self):
|
||||
return self._dz
|
||||
|
||||
def accept(self):
|
||||
self._dx = self.get_double_spin_box("doubleSpinBox_X")
|
||||
self._dy = self.get_double_spin_box("doubleSpinBox_Y")
|
||||
self._dz = self.get_double_spin_box("doubleSpinBox_Z")
|
||||
super().accept()
|
||||
|
||||
def reject(self):
|
||||
self.close()
|
||||
|
|
@ -267,3 +267,12 @@ class GeometryReachTableModel(PamhyrTableModel):
|
|||
)
|
||||
)
|
||||
self.layoutChanged.emit()
|
||||
|
||||
def shift(self, rows, dx, dy, dz):
|
||||
|
||||
self._undo.push(
|
||||
ShiftCommand(
|
||||
self._data, rows, dx, dy, dz
|
||||
)
|
||||
)
|
||||
self.layoutChanged.emit()
|
||||
|
|
|
|||
|
|
@ -82,3 +82,12 @@ class GeometryTranslate(MainTranslate):
|
|||
self._dict["Meshing"] = _translate(
|
||||
"Geometry", "Meshing"
|
||||
)
|
||||
self._dict["UpdateRK"] = _translate(
|
||||
"Geometry", "UpdateRK"
|
||||
)
|
||||
self._dict["Purge"] = _translate(
|
||||
"Geometry", "Purge"
|
||||
)
|
||||
self._dict["Shift"] = _translate(
|
||||
"Geometry", "Shift"
|
||||
)
|
||||
|
|
|
|||
|
|
@ -281,3 +281,32 @@ class PurgeCommand(QUndoCommand):
|
|||
def redo(self):
|
||||
for profile in self._reach._profiles:
|
||||
profile.purge(self._np_purge)
|
||||
|
||||
|
||||
class ShiftCommand(QUndoCommand):
|
||||
def __init__(self, reach, rows, dx, dy, dz):
|
||||
QUndoCommand.__init__(self)
|
||||
|
||||
self._reach = reach
|
||||
self._rows = rows
|
||||
self._dx = dx
|
||||
self._dy = dy
|
||||
self._dz = dz
|
||||
|
||||
self._old = []
|
||||
for profile in self._reach.profiles:
|
||||
self._old.append(profile.points.copy())
|
||||
|
||||
def undo(self):
|
||||
for i in self._rows:
|
||||
profile = self._reach.profiles[i]
|
||||
self._reach.profiles[i].shift(-self._dx,
|
||||
-self._dy,
|
||||
-self._dz)
|
||||
|
||||
def redo(self):
|
||||
for i in self._rows:
|
||||
profile = self._reach.profiles[i]
|
||||
self._reach.profiles[i].shift(self._dx,
|
||||
self._dy,
|
||||
self._dz)
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@ from View.Geometry.PlotRKZ import PlotRKZ
|
|||
from View.Geometry.MeshingDialog import MeshingDialog
|
||||
from View.Geometry.UpdateRKDialog import UpdateRKDialog
|
||||
from View.Geometry.PurgeDialog import PurgeDialog
|
||||
from View.Geometry.ShiftDialog import ShiftDialog
|
||||
from View.Geometry.Translate import GeometryTranslate
|
||||
from View.Geometry.Profile.Window import ProfileWindow
|
||||
|
||||
|
|
@ -205,6 +206,7 @@ class GeometryWindow(PamhyrWindow):
|
|||
"action_meshing": self.edit_meshing,
|
||||
"action_update_rk": self.update_rk,
|
||||
"action_purge": self.purge,
|
||||
"action_shift": self.shift,
|
||||
}
|
||||
|
||||
for action in actions:
|
||||
|
|
@ -511,10 +513,6 @@ class GeometryWindow(PamhyrWindow):
|
|||
self._table.move_down(row)
|
||||
self.select_current_profile()
|
||||
|
||||
def purge(self):
|
||||
self._table.purge()
|
||||
self.update_redraw()
|
||||
|
||||
def purge(self):
|
||||
try:
|
||||
dlg = PurgeDialog(
|
||||
|
|
@ -527,6 +525,28 @@ class GeometryWindow(PamhyrWindow):
|
|||
logger_exception(e)
|
||||
return
|
||||
|
||||
def shift(self):
|
||||
rows = sorted(
|
||||
list(
|
||||
set(
|
||||
[index.row() for index in self.tableView.selectedIndexes()]
|
||||
)
|
||||
)
|
||||
)
|
||||
try:
|
||||
dlg = ShiftDialog(
|
||||
trad=self._trad,
|
||||
parent=self
|
||||
)
|
||||
if dlg.exec():
|
||||
self._table.shift(rows,
|
||||
dlg.dx,
|
||||
dlg.dy,
|
||||
dlg.dz)
|
||||
except Exception as e:
|
||||
logger_exception(e)
|
||||
return
|
||||
|
||||
def duplicate(self):
|
||||
rows = [
|
||||
row.row() for row in
|
||||
|
|
@ -615,7 +635,7 @@ class GeometryWindow(PamhyrWindow):
|
|||
QSettings.UserScope, 'MyOrg'
|
||||
)
|
||||
|
||||
if self._study.filename != "" or self._study.filename is not None:
|
||||
if self._study.filename != "" and self._study.filename is not None:
|
||||
default_directory = os.path.basename(self._study.filename)
|
||||
current_dir = settings.value(
|
||||
'current_directory',
|
||||
|
|
|
|||
|
|
@ -200,7 +200,7 @@ class InitialConditionsWindow(PamhyrWindow):
|
|||
return rows[0].row()
|
||||
|
||||
def update(self):
|
||||
self.update(propagate=False)
|
||||
self._update(propagate=False)
|
||||
|
||||
def _update(self, propagate=True):
|
||||
self._update_plot()
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import logging
|
|||
|
||||
from functools import reduce
|
||||
from datetime import datetime
|
||||
from numpy import sqrt
|
||||
|
||||
from tools import timer
|
||||
from View.Tools.PamhyrPlot import PamhyrPlot
|
||||
|
|
@ -32,6 +33,11 @@ unit = {
|
|||
"elevation": "0-meter",
|
||||
"water_elevation": "0-meter",
|
||||
"discharge": "1-m3s",
|
||||
"velocity": "2-ms",
|
||||
"depth": "3-meter",
|
||||
"mean_depth": "3-meter",
|
||||
"froude": "4-dimensionless",
|
||||
"wet_area": "5-m2",
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -76,74 +82,155 @@ class CustomPlot(PamhyrPlot):
|
|||
reach = results.river.reach(self._reach)
|
||||
rk = reach.geometry.get_rk()
|
||||
z_min = reach.geometry.get_z_min()
|
||||
q = list(
|
||||
map(
|
||||
lambda p: p.get_ts_key(self._timestamp, "Q"),
|
||||
reach.profiles
|
||||
)
|
||||
)
|
||||
z = list(
|
||||
map(
|
||||
lambda p: p.get_ts_key(self._timestamp, "Z"),
|
||||
reach.profiles
|
||||
)
|
||||
)
|
||||
|
||||
# self.canvas.axes.set_xlim(
|
||||
# left=min(rk), right=max(rk)
|
||||
# )
|
||||
|
||||
meter_axes = self.canvas.axes
|
||||
m3S_axes = self.canvas.axes
|
||||
if "0-meter" in self._y_axes and "1-m3s" in self._y_axes:
|
||||
m3s_axes = self._axes["1-m3s"]
|
||||
shift = 0
|
||||
compt = 0
|
||||
for ax in sorted(self._axes):
|
||||
if compt == 0:
|
||||
self._axes[ax].spines['left'].set_position(('outward', shift))
|
||||
compt += 1
|
||||
else:
|
||||
self._axes[ax].spines['right'].set_position(('outward', shift))
|
||||
shift += 60
|
||||
|
||||
lines = {}
|
||||
if "elevation" in self._y:
|
||||
# meter_axes.set_ylim(
|
||||
# bottom=min(0, min(z_min)),
|
||||
# top=max(z_min) + 1
|
||||
# )
|
||||
|
||||
line = meter_axes.plot(
|
||||
ax = self._axes[unit["elevation"]]
|
||||
line = ax.plot(
|
||||
rk, z_min,
|
||||
color='grey', lw=1.,
|
||||
)
|
||||
lines["elevation"] = line
|
||||
|
||||
if "water_elevation" in self._y:
|
||||
# Water elevation
|
||||
water_z = list(
|
||||
map(
|
||||
lambda p: p.get_ts_key(self._timestamp, "Z"),
|
||||
reach.profiles
|
||||
)
|
||||
)
|
||||
|
||||
# meter_axes.set_ylim(
|
||||
# bottom=min(0, min(z_min)),
|
||||
# top=max(water_z) + 1
|
||||
# )
|
||||
|
||||
line = meter_axes.plot(
|
||||
rk, water_z, lw=1.,
|
||||
ax = self._axes[unit["water_elevation"]]
|
||||
line = ax.plot(
|
||||
rk, z, lw=1.,
|
||||
color='blue',
|
||||
)
|
||||
lines["water_elevation"] = line
|
||||
|
||||
if "elevation" in self._y:
|
||||
meter_axes.fill_between(
|
||||
rk, z_min, water_z,
|
||||
ax.fill_between(
|
||||
rk, z_min, z,
|
||||
color='blue', alpha=0.5, interpolate=True
|
||||
)
|
||||
|
||||
if "discharge" in self._y:
|
||||
q = list(
|
||||
map(
|
||||
lambda p: p.get_ts_key(self._timestamp, "Q"),
|
||||
reach.profiles
|
||||
)
|
||||
)
|
||||
|
||||
# m3s_axes.set_ylim(
|
||||
# bottom=min(0, min(q)),
|
||||
# top=max(q) + 1
|
||||
# )
|
||||
|
||||
line = m3s_axes.plot(
|
||||
ax = self._axes[unit["discharge"]]
|
||||
line = ax.plot(
|
||||
rk, q, lw=1.,
|
||||
color='r',
|
||||
)
|
||||
lines["discharge"] = line
|
||||
|
||||
if "velocity" in self._y:
|
||||
|
||||
ax = self._axes[unit["velocity"]]
|
||||
v = list(
|
||||
map(
|
||||
lambda p: p.geometry.speed(
|
||||
p.get_ts_key(self._timestamp, "Q"),
|
||||
p.get_ts_key(self._timestamp, "Z")),
|
||||
reach.profiles
|
||||
)
|
||||
)
|
||||
|
||||
line = ax.plot(
|
||||
rk, v, lw=1.,
|
||||
color='g',
|
||||
)
|
||||
lines["velocity"] = line
|
||||
|
||||
if "depth" in self._y:
|
||||
|
||||
ax = self._axes[unit["depth"]]
|
||||
d = list(
|
||||
map(
|
||||
lambda p: p.geometry.max_water_depth(
|
||||
p.get_ts_key(self._timestamp, "Z")),
|
||||
reach.profiles
|
||||
)
|
||||
)
|
||||
line = ax.plot(
|
||||
rk, d,
|
||||
color='brown', lw=1.,
|
||||
)
|
||||
lines["depth"] = line
|
||||
|
||||
if "mean_depth" in self._y:
|
||||
|
||||
ax = self._axes[unit["mean_depth"]]
|
||||
d = list(
|
||||
map(
|
||||
lambda p: p.geometry.mean_water_depth(
|
||||
p.get_ts_key(self._timestamp, "Z")),
|
||||
reach.profiles
|
||||
)
|
||||
)
|
||||
|
||||
line = ax.plot(
|
||||
rk, d,
|
||||
color='orange', lw=1.,
|
||||
)
|
||||
lines["mean_depth"] = line
|
||||
|
||||
if "froude" in self._y:
|
||||
|
||||
ax = self._axes[unit["froude"]]
|
||||
fr = list(
|
||||
map(
|
||||
lambda p:
|
||||
p.geometry.speed(
|
||||
p.get_ts_key(self._timestamp, "Q"),
|
||||
p.get_ts_key(self._timestamp, "Z")) /
|
||||
sqrt(9.81 * (
|
||||
p.geometry.wet_area(
|
||||
p.get_ts_key(self._timestamp, "Z")) /
|
||||
p.geometry.wet_width(
|
||||
p.get_ts_key(self._timestamp, "Z"))
|
||||
)),
|
||||
reach.profiles
|
||||
)
|
||||
)
|
||||
|
||||
line = ax.plot(
|
||||
rk, fr, color='black', linestyle='--', lw=1.,
|
||||
)
|
||||
lines["froude"] = line
|
||||
|
||||
if "wet_area" in self._y:
|
||||
|
||||
ax = self._axes[unit["wet_area"]]
|
||||
d = list(
|
||||
map(
|
||||
lambda p: p.geometry.wet_area(
|
||||
p.get_ts_key(self._timestamp, "Z")),
|
||||
reach.profiles
|
||||
)
|
||||
)
|
||||
|
||||
line = ax.plot(
|
||||
rk, d,
|
||||
color='blue', linestyle='--', lw=1.,
|
||||
)
|
||||
lines["wet_area"] = line
|
||||
|
||||
# Legend
|
||||
lns = reduce(
|
||||
lambda acc, line: acc + line,
|
||||
|
|
@ -151,7 +238,7 @@ class CustomPlot(PamhyrPlot):
|
|||
[]
|
||||
)
|
||||
labs = list(map(lambda line: self._trad[line], lines))
|
||||
self.canvas.axes.legend(lns, labs, loc="lower left")
|
||||
self.canvas.axes.legend(lns, labs, loc="best")
|
||||
|
||||
def _customize_x_axes_time(self, ts, mode="time"):
|
||||
# Custom time display
|
||||
|
|
@ -198,79 +285,137 @@ class CustomPlot(PamhyrPlot):
|
|||
reach = results.river.reach(self._reach)
|
||||
profile = reach.profile(self._profile)
|
||||
|
||||
meter_axes = self.canvas.axes
|
||||
m3S_axes = self.canvas.axes
|
||||
if "0-meter" in self._y_axes and "1-m3s" in self._y_axes:
|
||||
m3s_axes = self._axes["1-m3s"]
|
||||
shift = 0
|
||||
compt = 0
|
||||
for ax in sorted(self._axes):
|
||||
if compt == 0:
|
||||
self._axes[ax].spines['left'].set_position(('outward', shift))
|
||||
compt += 1
|
||||
else:
|
||||
self._axes[ax].spines['right'].set_position(('outward', shift))
|
||||
shift += 60
|
||||
|
||||
ts = list(results.get("timestamps"))
|
||||
ts.sort()
|
||||
|
||||
# self.canvas.axes.set_xlim(
|
||||
# left=min(ts), right=max(ts)
|
||||
# )
|
||||
q = profile.get_key("Q")
|
||||
z = profile.get_key("Z")
|
||||
z_min = profile.geometry.z_min()
|
||||
ts_z_min = list(
|
||||
map(
|
||||
lambda ts: z_min,
|
||||
ts
|
||||
)
|
||||
)
|
||||
|
||||
x = ts
|
||||
lines = {}
|
||||
if "elevation" in self._y:
|
||||
# Z min is constant in time
|
||||
z_min = profile.geometry.z_min()
|
||||
ts_z_min = list(
|
||||
map(
|
||||
lambda ts: z_min,
|
||||
ts
|
||||
)
|
||||
)
|
||||
|
||||
line = meter_axes.plot(
|
||||
ax = self._axes[unit["elevation"]]
|
||||
|
||||
line = ax.plot(
|
||||
ts, ts_z_min,
|
||||
color='grey', lw=1.
|
||||
)
|
||||
lines["elevation"] = line
|
||||
|
||||
if "water_elevation" in self._y:
|
||||
# Water elevation
|
||||
z = profile.get_key("Z")
|
||||
|
||||
# meter_axes.set_ylim(
|
||||
# bottom=min(0, min(z)),
|
||||
# top=max(z) + 1
|
||||
# )
|
||||
|
||||
line = meter_axes.plot(
|
||||
ax = self._axes[unit["water_elevation"]]
|
||||
line = ax.plot(
|
||||
ts, z, lw=1.,
|
||||
color='b',
|
||||
)
|
||||
lines["water_elevation"] = line
|
||||
|
||||
if "elevation" in self._y:
|
||||
z_min = profile.geometry.z_min()
|
||||
ts_z_min = list(
|
||||
map(
|
||||
lambda ts: z_min,
|
||||
ts
|
||||
)
|
||||
)
|
||||
|
||||
meter_axes.fill_between(
|
||||
ax.fill_between(
|
||||
ts, ts_z_min, z,
|
||||
color='blue', alpha=0.5, interpolate=True
|
||||
)
|
||||
|
||||
if "discharge" in self._y:
|
||||
q = profile.get_key("Q")
|
||||
|
||||
# m3s_axes.set_ylim(
|
||||
# bottom=min(0, min(q)),
|
||||
# top=max(q) + 1
|
||||
# )
|
||||
|
||||
line = m3s_axes.plot(
|
||||
ax = self._axes[unit["discharge"]]
|
||||
line = ax.plot(
|
||||
ts, q, lw=1.,
|
||||
color='r',
|
||||
)
|
||||
lines["discharge"] = line
|
||||
|
||||
if "velocity" in self._y:
|
||||
|
||||
ax = self._axes[unit["velocity"]]
|
||||
v = list(
|
||||
map(
|
||||
lambda q, z: profile.geometry.speed(q, z),
|
||||
q, z
|
||||
)
|
||||
)
|
||||
|
||||
line = ax.plot(
|
||||
ts, v, lw=1.,
|
||||
color='g',
|
||||
)
|
||||
lines["velocity"] = line
|
||||
|
||||
if "depth" in self._y:
|
||||
|
||||
ax = self._axes[unit["depth"]]
|
||||
d = list(
|
||||
map(lambda z: profile.geometry.max_water_depth(z), z)
|
||||
)
|
||||
|
||||
line = ax.plot(
|
||||
ts, d,
|
||||
color='brown', lw=1.,
|
||||
)
|
||||
lines["depth"] = line
|
||||
|
||||
if "mean_depth" in self._y:
|
||||
|
||||
ax = self._axes[unit["mean_depth"]]
|
||||
d = list(
|
||||
map(lambda z: profile.geometry.mean_water_depth(z), z)
|
||||
)
|
||||
|
||||
line = ax.plot(
|
||||
ts, d,
|
||||
color='orange', lw=1.,
|
||||
)
|
||||
lines["depth"] = line
|
||||
|
||||
if "froude" in self._y:
|
||||
|
||||
ax = self._axes[unit["froude"]]
|
||||
d = list(
|
||||
map(lambda z, q:
|
||||
profile.geometry.speed(q, z) /
|
||||
sqrt(9.81 * (
|
||||
profile.geometry.wet_area(z) /
|
||||
profile.geometry.wet_width(z))
|
||||
), z, q)
|
||||
)
|
||||
|
||||
line = ax.plot(
|
||||
ts, d, color='black', linestyle='--', lw=1.,
|
||||
)
|
||||
lines["froude"] = line
|
||||
|
||||
if "wet_area" in self._y:
|
||||
|
||||
ax = self._axes[unit["wet_area"]]
|
||||
d = list(
|
||||
map(lambda z: profile.geometry.wet_area(z), z)
|
||||
)
|
||||
|
||||
line = ax.plot(
|
||||
ts, d, color='blue', linestyle='--', lw=1.,
|
||||
)
|
||||
lines["wet_area"] = line
|
||||
|
||||
self._customize_x_axes_time(ts)
|
||||
|
||||
# Legend
|
||||
|
|
@ -280,7 +425,7 @@ class CustomPlot(PamhyrPlot):
|
|||
[]
|
||||
)
|
||||
labs = list(map(lambda line: self._trad[line], lines))
|
||||
self.canvas.axes.legend(lns, labs, loc="lower left")
|
||||
self.canvas.axes.legend(lns, labs, loc="best")
|
||||
|
||||
@timer
|
||||
def draw(self):
|
||||
|
|
@ -300,6 +445,7 @@ class CustomPlot(PamhyrPlot):
|
|||
color='black', fontsize=10
|
||||
)
|
||||
|
||||
self._axes[self._y_axes[0]] = self.canvas.axes
|
||||
for axes in self._y_axes[1:]:
|
||||
if axes in self._axes:
|
||||
self._axes[axes].clear()
|
||||
|
|
@ -316,8 +462,22 @@ class CustomPlot(PamhyrPlot):
|
|||
self._draw_rk()
|
||||
elif self._x == "time":
|
||||
self._draw_time()
|
||||
if self._x == "rk":
|
||||
reach = self.data.river.reach(self._reach)
|
||||
profile = reach.profile(self._profile)
|
||||
x = profile.rk
|
||||
elif self._x == "time":
|
||||
x = self._timestamp
|
||||
|
||||
self._current, = self.canvas.axes.plot(
|
||||
[x, x],
|
||||
self.canvas.axes.get_ylim(),
|
||||
# label=self.label_timestamp,
|
||||
color='grey',
|
||||
linestyle="dashed",
|
||||
lw=1.,
|
||||
)
|
||||
|
||||
self.canvas.figure.tight_layout()
|
||||
self.canvas.figure.canvas.draw_idle()
|
||||
if self.toolbar is not None:
|
||||
self.toolbar.update()
|
||||
|
|
@ -326,6 +486,7 @@ class CustomPlot(PamhyrPlot):
|
|||
def update(self):
|
||||
if not self._init:
|
||||
self.draw()
|
||||
self.draw_current()
|
||||
return
|
||||
|
||||
def set_reach(self, reach_id):
|
||||
|
|
@ -339,9 +500,23 @@ class CustomPlot(PamhyrPlot):
|
|||
|
||||
if self._x != "rk":
|
||||
self.update()
|
||||
else:
|
||||
self.draw_current()
|
||||
|
||||
def set_timestamp(self, timestamp):
|
||||
self._timestamp = timestamp
|
||||
|
||||
if self._x != "time":
|
||||
self.update()
|
||||
else:
|
||||
self.draw_current()
|
||||
|
||||
def draw_current(self):
|
||||
if self._x == "rk":
|
||||
reach = self.data.river.reach(self._reach)
|
||||
profile = reach.profile(self._profile)
|
||||
x = profile.rk
|
||||
elif self._x == "time":
|
||||
x = self._timestamp
|
||||
self._current.set_data([x, x], self.canvas.axes.get_ylim())
|
||||
self.canvas.figure.canvas.draw_idle()
|
||||
|
|
|
|||
|
|
@ -40,6 +40,14 @@ class CustomPlotTranslate(ResultsTranslate):
|
|||
self._dict['elevation'] = _translate(
|
||||
"CustomPlot", "Bed elevation (m)"
|
||||
)
|
||||
self._dict['velocity'] = self._dict["unit_speed"]
|
||||
self._dict['width'] = self._dict["unit_width"]
|
||||
self._dict['max_depth'] = self._dict["unit_max_height"]
|
||||
self._dict['mean_depth'] = self._dict["unit_mean_height"]
|
||||
self._dict['wet_area'] = self._dict["unit_wet_area"]
|
||||
self._dict['wet_perimeter'] = self._dict["unit_wet_perimeter"]
|
||||
self._dict['hydraulic_radius'] = self._dict["unit_hydraulic_radius"]
|
||||
self._dict['froude'] = self._dict["unit_froude"]
|
||||
|
||||
# Unit corresponding long name (plot axes display)
|
||||
|
||||
|
|
@ -47,6 +55,10 @@ class CustomPlotTranslate(ResultsTranslate):
|
|||
"CustomPlot", "Bed elevation (m)"
|
||||
)
|
||||
self._dict['1-m3s'] = self._dict["unit_discharge"]
|
||||
self._dict['2-ms'] = self._dict["unit_speed"]
|
||||
self._dict['3-meter'] = self._dict["unit_height"]
|
||||
self._dict['4-dimensionless'] = self._dict["unit_froude"]
|
||||
self._dict['5-m2'] = self._dict["wet_area"]
|
||||
|
||||
# SubDict
|
||||
|
||||
|
|
@ -58,4 +70,9 @@ class CustomPlotTranslate(ResultsTranslate):
|
|||
"elevation": self._dict["elevation"],
|
||||
"water_elevation": self._dict["water_elevation"],
|
||||
"discharge": self._dict["discharge"],
|
||||
"velocity": self._dict["velocity"],
|
||||
"depth": self._dict["max_depth"],
|
||||
"mean_depth": self._dict["mean_depth"],
|
||||
"froude": self._dict["froude"],
|
||||
"wet_area": self._dict["wet_area"],
|
||||
}
|
||||
|
|
|
|||
|
|
@ -88,13 +88,14 @@ class PlotH(PamhyrPlot):
|
|||
|
||||
self.draw_max(reach)
|
||||
self.draw_data(reach, profile)
|
||||
self.draw_current(reach, profile)
|
||||
self.draw_current()
|
||||
|
||||
self.set_ticks_time_formater()
|
||||
|
||||
self.enable_legend()
|
||||
|
||||
self.idle()
|
||||
self.update_current()
|
||||
self._init = True
|
||||
|
||||
def draw_data(self, reach, profile):
|
||||
|
|
@ -111,21 +112,12 @@ class PlotH(PamhyrPlot):
|
|||
**self.plot_default_kargs
|
||||
)
|
||||
|
||||
def draw_current(self, reach, profile):
|
||||
min_y, max_y = reduce(
|
||||
lambda acc, p: (
|
||||
acc[0] + [min(p.get_key("Q"))],
|
||||
acc[1] + [max(p.get_key("Q"))]
|
||||
),
|
||||
reach.profiles,
|
||||
([], [])
|
||||
)
|
||||
|
||||
def draw_current(self):
|
||||
self._current, = self.canvas.axes.plot(
|
||||
[self._current_timestamp, self._current_timestamp],
|
||||
[min(min_y), max(max_y)],
|
||||
self.canvas.axes.get_ylim(),
|
||||
# label=self.label_timestamp,
|
||||
color=self.color_plot_river_bottom,
|
||||
color="grey",
|
||||
linestyle="dashed",
|
||||
lw=1.,
|
||||
)
|
||||
|
|
@ -162,14 +154,14 @@ class PlotH(PamhyrPlot):
|
|||
|
||||
def set_timestamp(self, timestamp):
|
||||
self._current_timestamp = timestamp
|
||||
self.update()
|
||||
self.update_current()
|
||||
self.update_idle()
|
||||
|
||||
def update(self):
|
||||
if not self._init:
|
||||
self.draw()
|
||||
|
||||
self.update_data()
|
||||
|
||||
self.update_idle()
|
||||
|
||||
def update_data(self):
|
||||
|
|
@ -181,8 +173,13 @@ class PlotH(PamhyrPlot):
|
|||
|
||||
self._line.set_data(x, y)
|
||||
|
||||
_, min_max = self._current.get_data()
|
||||
self._current.set_data(
|
||||
self._current_timestamp,
|
||||
min_max
|
||||
self.canvas.axes.get_ylim()
|
||||
)
|
||||
|
||||
def update_current(self):
|
||||
self._current.set_data(
|
||||
self._current_timestamp,
|
||||
self.canvas.axes.get_ylim()
|
||||
)
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@
|
|||
import logging
|
||||
import traceback
|
||||
|
||||
from numpy import sqrt
|
||||
|
||||
from tools import timer, trace
|
||||
|
||||
from PyQt5.QtGui import (
|
||||
|
|
@ -86,12 +88,46 @@ class TableModel(PamhyrTableModel):
|
|||
elif self._headers[column] == "discharge":
|
||||
v = self._lst[row].get_ts_key(self._timestamp, "Q")
|
||||
return f"{v:.4f}"
|
||||
elif self._headers[column] == "speed":
|
||||
elif self._headers[column] == "velocity":
|
||||
q = self._lst[row].get_ts_key(self._timestamp, "Q")
|
||||
z = self._lst[row].get_ts_key(self._timestamp, "Z")
|
||||
|
||||
v = self._lst[row].geometry.speed(q, z)
|
||||
return f"{v:.4f}"
|
||||
elif self._headers[column] == "width":
|
||||
z = self._lst[row].get_ts_key(self._timestamp, "Z")
|
||||
v = self._lst[row].geometry.wet_width(z)
|
||||
return f"{v:.4f}"
|
||||
elif self._headers[column] == "max_depth":
|
||||
z = self._lst[row].get_ts_key(self._timestamp, "Z")
|
||||
v = self._lst[row].geometry.max_water_depth(z)
|
||||
return f"{v:.4f}"
|
||||
elif self._headers[column] == "mean_depth":
|
||||
z = self._lst[row].get_ts_key(self._timestamp, "Z")
|
||||
v = self._lst[row].geometry.mean_water_depth(z)
|
||||
return f"{v:.4f}"
|
||||
elif self._headers[column] == "wet_area":
|
||||
z = self._lst[row].get_ts_key(self._timestamp, "Z")
|
||||
v = self._lst[row].geometry.wet_area(z)
|
||||
return f"{v:.4f}"
|
||||
elif self._headers[column] == "wet_perimeter":
|
||||
z = self._lst[row].get_ts_key(self._timestamp, "Z")
|
||||
v = self._lst[row].geometry.wet_perimeter(z)
|
||||
return f"{v:.4f}"
|
||||
elif self._headers[column] == "hydraulic_radius":
|
||||
z = self._lst[row].get_ts_key(self._timestamp, "Z")
|
||||
v = self._lst[row].geometry.wet_radius(z)
|
||||
return f"{v:.4f}"
|
||||
elif self._headers[column] == "froude":
|
||||
q = self._lst[row].get_ts_key(self._timestamp, "Q")
|
||||
z = self._lst[row].get_ts_key(self._timestamp, "Z")
|
||||
v = self._lst[row].geometry.speed(q, z)
|
||||
a = self._lst[row].geometry.wet_area(z)
|
||||
b = self._lst[row].geometry.wet_width(z)
|
||||
froude = v / sqrt(9.81 * (a / b))
|
||||
return f"{froude:.4f}"
|
||||
else:
|
||||
v = 0.0
|
||||
return f"{v:.4f}"
|
||||
|
||||
return QVariant()
|
||||
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ from PyQt5.QtWidgets import (
|
|||
QFileDialog, QTableView, QAbstractItemView,
|
||||
QUndoStack, QShortcut, QAction, QItemDelegate,
|
||||
QComboBox, QVBoxLayout, QHeaderView, QTabWidget,
|
||||
QSlider, QLabel, QWidget, QGridLayout,
|
||||
QSlider, QLabel, QWidget, QGridLayout, QTabBar
|
||||
)
|
||||
|
||||
from View.Tools.Plot.PamhyrCanvas import MplCanvas
|
||||
|
|
@ -108,9 +108,9 @@ class ResultsWindow(PamhyrWindow):
|
|||
try:
|
||||
self._timestamps = sorted(list(self._results.get("timestamps")))
|
||||
|
||||
self.setup_slider()
|
||||
self.setup_table()
|
||||
self.setup_plots()
|
||||
self.setup_slider()
|
||||
self.setup_statusbar()
|
||||
self.setup_connections()
|
||||
except Exception as e:
|
||||
|
|
@ -128,12 +128,11 @@ class ResultsWindow(PamhyrWindow):
|
|||
undo=self._undo_stack,
|
||||
opt_data=t
|
||||
)
|
||||
self._table[t]._timestamp = self._timestamps[
|
||||
self._slider_time.value()]
|
||||
|
||||
def setup_slider(self):
|
||||
self._slider_profile = self.find(QSlider, f"verticalSlider_profile")
|
||||
default_reach = self._results.river.reach(0)
|
||||
self._slider_profile.setMaximum(len(default_reach.profiles) - 1)
|
||||
self._slider_profile.setValue(0)
|
||||
|
||||
self._slider_time = self.find(QSlider, f"horizontalSlider_time")
|
||||
self._slider_time.setMaximum(len(self._timestamps) - 1)
|
||||
|
|
@ -158,6 +157,12 @@ class ResultsWindow(PamhyrWindow):
|
|||
|
||||
def setup_plots(self):
|
||||
self.canvas = MplCanvas(width=5, height=4, dpi=100)
|
||||
tab_widget = self.find(QTabWidget, f"tabWidget")
|
||||
tab_widget.setTabsClosable(True)
|
||||
tab_widget.tabCloseRequested.connect(self.delete_tab)
|
||||
tab_widget.tabBar().setTabButton(0, QTabBar.RightSide, None)
|
||||
tab_widget.tabBar().setTabButton(1, QTabBar.RightSide, None)
|
||||
tab_widget.tabBar().setTabButton(2, QTabBar.RightSide, None)
|
||||
self.canvas.setObjectName("canvas")
|
||||
self.toolbar = PamhyrPlotToolbar(
|
||||
self.canvas, self, items=[
|
||||
|
|
@ -303,7 +308,8 @@ class ResultsWindow(PamhyrWindow):
|
|||
actions = {
|
||||
"action_reload": self._reload,
|
||||
"action_add": self._add_custom_plot,
|
||||
"action_export": self.export,
|
||||
# "action_export": self.export,
|
||||
"action_export": self.export_current,
|
||||
}
|
||||
|
||||
for action in actions:
|
||||
|
|
@ -327,8 +333,6 @@ class ResultsWindow(PamhyrWindow):
|
|||
|
||||
self._table[t].dataChanged.connect(fun[t])
|
||||
|
||||
self._slider_profile.valueChanged.connect(
|
||||
self._set_current_profile_slider)
|
||||
self._slider_time.valueChanged.connect(self._set_current_timestamp)
|
||||
self._button_play.setChecked(False)
|
||||
self._button_play.clicked.connect(self._pause)
|
||||
|
|
@ -442,7 +446,6 @@ class ResultsWindow(PamhyrWindow):
|
|||
|
||||
ind = indexes[0].row()
|
||||
self.update(profile_id=ind)
|
||||
self._slider_profile.setValue(ind)
|
||||
|
||||
def _set_current_profile_raw_data(self):
|
||||
table = self.find(QTableView, f"tableView_raw_data")
|
||||
|
|
@ -452,11 +455,6 @@ class ResultsWindow(PamhyrWindow):
|
|||
|
||||
ind = indexes[0].row()
|
||||
self.update(profile_id=ind)
|
||||
self._slider_profile.setValue(ind)
|
||||
|
||||
def _set_current_profile_slider(self):
|
||||
pid = self._slider_profile.value()
|
||||
self.update(profile_id=pid)
|
||||
|
||||
def _set_current_timestamp(self):
|
||||
timestamp = self._timestamps[self._slider_time.value()]
|
||||
|
|
@ -500,7 +498,7 @@ class ResultsWindow(PamhyrWindow):
|
|||
tab_widget = self.find(QTabWidget, f"tabWidget")
|
||||
|
||||
# This plot already exists
|
||||
if name in self._additional_plot:
|
||||
if name in [tab_widget.tabText(i) for i in range(tab_widget.count())]:
|
||||
tab_widget.setCurrentWidget(
|
||||
tab_widget.findChild(QWidget, wname)
|
||||
)
|
||||
|
|
@ -591,12 +589,15 @@ class ResultsWindow(PamhyrWindow):
|
|||
)
|
||||
|
||||
def export_to(self, directory):
|
||||
timestamps = sorted(self._results.get("timestamps"))
|
||||
for reach in self._results.river.reachs:
|
||||
self.export_reach(reach, directory)
|
||||
self.export_reach(reach, directory, timestamps)
|
||||
|
||||
def export_reach(self, reach, directory):
|
||||
def export_reach(self, reach, directory, timestamps):
|
||||
name = reach.name
|
||||
name = name.replace(" ", "-")
|
||||
if len(timestamps) == 1:
|
||||
name = f"{name}_t{timestamps[0]}"
|
||||
|
||||
file_name = os.path.join(
|
||||
directory,
|
||||
|
|
@ -606,28 +607,40 @@ class ResultsWindow(PamhyrWindow):
|
|||
with open(file_name, 'w', newline='') as csvfile:
|
||||
writer = csv.writer(csvfile, delimiter=',',
|
||||
quotechar='|', quoting=csv.QUOTE_MINIMAL)
|
||||
writer.writerow(["name", "rk", "data-file"])
|
||||
for profile in reach.profiles:
|
||||
p_file_name = os.path.join(
|
||||
directory,
|
||||
f"cs_{profile.geometry.id}.csv"
|
||||
)
|
||||
if len(timestamps) > 1:
|
||||
writer.writerow(["name", "rk", "data-file"])
|
||||
for profile in reach.profiles:
|
||||
p_file_name = os.path.join(
|
||||
directory,
|
||||
f"cs_{profile.geometry.id}.csv"
|
||||
)
|
||||
|
||||
writer.writerow([
|
||||
profile.name,
|
||||
profile.rk,
|
||||
p_file_name
|
||||
])
|
||||
writer.writerow([
|
||||
profile.name,
|
||||
profile.rk,
|
||||
p_file_name
|
||||
])
|
||||
|
||||
self.export_profile(reach, profile, p_file_name)
|
||||
self.export_profile(reach,
|
||||
profile,
|
||||
p_file_name,
|
||||
timestamps)
|
||||
else:
|
||||
ts = timestamps[0]
|
||||
writer.writerow(self._table["raw_data"]._headers)
|
||||
for row in range(self._table["raw_data"].rowCount()):
|
||||
line = []
|
||||
for column in range(self._table["raw_data"].columnCount()):
|
||||
index = self._table["raw_data"].index(row, column)
|
||||
line.append(self._table["raw_data"].data(index))
|
||||
writer.writerow(line)
|
||||
|
||||
def export_profile(self, reach, profile, file_name):
|
||||
def export_profile(self, reach, profile, file_name, timestamps):
|
||||
with open(file_name, 'w', newline='') as csvfile:
|
||||
writer = csv.writer(csvfile, delimiter=',',
|
||||
quotechar='|', quoting=csv.QUOTE_MINIMAL)
|
||||
|
||||
writer.writerow(["timestamp", "z", "q"])
|
||||
timestamps = sorted(self._results.get("timestamps"))
|
||||
|
||||
for ts in timestamps:
|
||||
writer.writerow([
|
||||
|
|
@ -635,3 +648,18 @@ class ResultsWindow(PamhyrWindow):
|
|||
profile.get_ts_key(ts, "Z"),
|
||||
profile.get_ts_key(ts, "Q"),
|
||||
])
|
||||
|
||||
def export_current(self):
|
||||
self.file_dialog(
|
||||
select_file=False,
|
||||
callback=lambda d: self.export_current_to(d[0])
|
||||
)
|
||||
|
||||
def export_current_to(self, directory):
|
||||
reach = self._results.river.reachs[self._get_current_reach()]
|
||||
self.export_reach(reach, directory, [self._get_current_timestamp()])
|
||||
|
||||
def delete_tab(self, index):
|
||||
tab_widget = self.find(QTabWidget, f"tabWidget")
|
||||
self._additional_plot.pop(tab_widget.tabText(index))
|
||||
tab_widget.removeTab(index)
|
||||
|
|
|
|||
|
|
@ -57,5 +57,12 @@ class ResultsTranslate(MainTranslate):
|
|||
"name": _translate("Results", "Profile"),
|
||||
"water_elevation": self._dict["unit_water_elevation"],
|
||||
"discharge": self._dict["unit_discharge"],
|
||||
"speed": self._dict["unit_speed"],
|
||||
"velocity": self._dict["unit_speed"],
|
||||
"width": self._dict["unit_width"],
|
||||
"max_depth": self._dict["unit_max_height"],
|
||||
"mean_depth": self._dict["unit_mean_height"],
|
||||
"wet_area": self._dict["unit_wet_area"],
|
||||
"wet_perimeter": self._dict["unit_wet_perimeter"],
|
||||
"hydraulic_radius": self._dict["unit_hydraulic_radius"],
|
||||
"froude": self._dict["unit_froude"],
|
||||
}
|
||||
|
|
|
|||
|
|
@ -192,7 +192,6 @@ class PamhyrPlot(APlot):
|
|||
self.canvas.axes.autoscale_view(True, True, True)
|
||||
self.canvas.axes.autoscale()
|
||||
|
||||
self.canvas.figure.tight_layout()
|
||||
self.canvas.figure.canvas.draw_idle()
|
||||
|
||||
self.toolbar_update()
|
||||
|
|
@ -205,7 +204,6 @@ class PamhyrPlot(APlot):
|
|||
self.canvas.axes.autoscale_view(True, True, True)
|
||||
self.canvas.axes.autoscale()
|
||||
|
||||
self.canvas.figure.tight_layout()
|
||||
self.canvas.figure.canvas.draw_idle()
|
||||
|
||||
self.toolbar_update()
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ class MplCanvas(FigureCanvasQTAgg):
|
|||
fig = Figure(
|
||||
figsize=(width, height),
|
||||
dpi=dpi,
|
||||
layout='tight',
|
||||
layout='constrained',
|
||||
)
|
||||
super(MplCanvas, self).__init__(fig)
|
||||
|
||||
|
|
@ -36,7 +36,6 @@ class MplCanvas(FigureCanvasQTAgg):
|
|||
self.axes.yaxis.tick_left()
|
||||
self.axes.xaxis.tick_bottom()
|
||||
self.axes.spines[['top', 'right']].set_color('none')
|
||||
self.figure.tight_layout()
|
||||
self.add_arrows()
|
||||
|
||||
def add_arrows(self):
|
||||
|
|
|
|||
|
|
@ -55,16 +55,18 @@ class UnitTranslate(CommonWordTranslate):
|
|||
def __init__(self):
|
||||
super(UnitTranslate, self).__init__()
|
||||
|
||||
self._dict["unit_rk"] = _translate("Unit", "River Kilometric (m)")
|
||||
self._dict["unit_rk"] = _translate("Unit", "River Kilometer (m)")
|
||||
self._dict["unit_width"] = _translate("Unit", "Width (m)")
|
||||
self._dict["unit_height"] = _translate("Unit", "Height (m)")
|
||||
self._dict["unit_height"] = _translate("Unit", "Depth (m)")
|
||||
self._dict["unit_max_height"] = _translate("Unit", "Max Depth (m)")
|
||||
self._dict["unit_mean_height"] = _translate("Unit", "Mean Depth (m)")
|
||||
self._dict["unit_diameter"] = _translate("Unit", "Diameter (m)")
|
||||
self._dict["unit_thickness"] = _translate("Unit", "Thickness (m)")
|
||||
self._dict["unit_elevation"] = _translate("Unit", "Elevation (m)")
|
||||
self._dict["unit_water_elevation"] = _translate(
|
||||
"Unit", "Water elevation (m)"
|
||||
)
|
||||
self._dict["unit_speed"] = _translate("Unit", "Speed (m/s)")
|
||||
self._dict["unit_speed"] = _translate("Unit", "Velocity (m/s)")
|
||||
self._dict["unit_discharge"] = _translate("Unit", "Discharge (m³/s)")
|
||||
self._dict["unit_area"] = _translate("Unit", "Area (hectare)")
|
||||
|
||||
|
|
@ -74,6 +76,15 @@ class UnitTranslate(CommonWordTranslate):
|
|||
self._dict["unit_date_s"] = _translate("Unit", "Date (sec)")
|
||||
self._dict["unit_date_iso"] = _translate("Unit", "Date (ISO format)")
|
||||
|
||||
self._dict["unit_wet_area"] = _translate("Unit", "Wet Area (m²)")
|
||||
self._dict["unit_wet_perimeter"] = _translate(
|
||||
"Unit", "Wet Perimeter (m)"
|
||||
)
|
||||
self._dict["unit_hydraulic_radius"] = _translate(
|
||||
"Unit", "Hydraulic Radius (m)"
|
||||
)
|
||||
self._dict["unit_froude"] = _translate("Unit", "Froude number")
|
||||
|
||||
|
||||
class MainTranslate(UnitTranslate):
|
||||
def __init__(self):
|
||||
|
|
|
|||
|
|
@ -0,0 +1,98 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Dialog</class>
|
||||
<widget class="QDialog" name="Dialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>356</width>
|
||||
<height>107</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Options</string>
|
||||
</property>
|
||||
<property name="accessibleName">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="locale">
|
||||
<locale language="English" country="Europe"/>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="2" column="0">
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Slope</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDoubleSpinBox" name="doubleSpinBox">
|
||||
<property name="decimals">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>999999.998999999952503</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="EstimateButton">
|
||||
<property name="text">
|
||||
<string>Estimate</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>Dialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>Dialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</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/>
|
||||
|
|
|
|||
|
|
@ -92,6 +92,7 @@
|
|||
<addaction name="action_meshing"/>
|
||||
<addaction name="action_update_rk"/>
|
||||
<addaction name="action_purge"/>
|
||||
<addaction name="action_shift"/>
|
||||
</widget>
|
||||
<action name="action_import">
|
||||
<property name="icon">
|
||||
|
|
@ -226,6 +227,14 @@
|
|||
<string>Purge cross-sections to keep a given number of points</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_shift">
|
||||
<property name="text">
|
||||
<string>Shift</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Shift selected sections coordinates</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,134 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Dialog</class>
|
||||
<widget class="QDialog" name="Dialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>381</width>
|
||||
<height>144</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Dialog</string>
|
||||
</property>
|
||||
<property name="layoutDirection">
|
||||
<enum>Qt::LeftToRight</enum>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_4">
|
||||
<item row="3" column="0">
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Y coordinate</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_1">
|
||||
<property name="text">
|
||||
<string>X coordinate</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QDoubleSpinBox" name="doubleSpinBox_Y">
|
||||
<property name="decimals">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>-99999999.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>99999999.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QDoubleSpinBox" name="doubleSpinBox_X">
|
||||
<property name="decimals">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>-99999999.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>99999999.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Z coordinate</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QDoubleSpinBox" name="doubleSpinBox_Z">
|
||||
<property name="decimals">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>-99999999.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>99999999.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>Dialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>Dialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
|
|
@ -27,14 +27,14 @@
|
|||
<item>
|
||||
<widget class="QPushButton" name="pushButton_generate_1">
|
||||
<property name="text">
|
||||
<string>Generate from height</string>
|
||||
<string>Generate height</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_generate_2">
|
||||
<property name="text">
|
||||
<string>Generate from discharge</string>
|
||||
<string>Generate discharge</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
|
|||
|
|
@ -39,19 +39,6 @@
|
|||
<item>
|
||||
<widget class="QTableView" name="tableView_profile"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSlider" name="verticalSlider_profile">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="invertedAppearance">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="invertedControls">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
|
|
@ -145,7 +132,10 @@
|
|||
<item row="0" column="0">
|
||||
<widget class="QTabWidget" name="tabWidget">
|
||||
<property name="currentIndex">
|
||||
<number>1</number>
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="tabsClosable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="tab_4">
|
||||
<attribute name="title">
|
||||
|
|
|
|||
|
|
@ -2168,13 +2168,13 @@
|
|||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/InitialConditions.ui" line="30"/>
|
||||
<source>Generate from height</source>
|
||||
<translation>Générer pour une hauteur donnée</translation>
|
||||
<source>Generate height</source>
|
||||
<translation>Générer une hauteur</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/InitialConditions.ui" line="37"/>
|
||||
<source>Generate from discharge</source>
|
||||
<translation>Générer pour un débit donné</translation>
|
||||
<source>Generate discharge</source>
|
||||
<translation>Générer un débit</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../View/ui/InitialConditions.ui" line="98"/>
|
||||
|
|
@ -3057,7 +3057,7 @@
|
|||
</message>
|
||||
<message>
|
||||
<location filename="../View/Translate.py" line="57"/>
|
||||
<source>Height (m)</source>
|
||||
<source>Depth (m)</source>
|
||||
<translation>Hauteur (m)</translation>
|
||||
</message>
|
||||
<message>
|
||||
|
|
|
|||
Loading…
Reference in New Issue