mirror of https://gitlab.com/pamhyr/pamhyr2
geomerty: Add Sylvain work and start cleaning code (doesn't works).
parent
f4dd46cd1a
commit
35ba2599fb
|
|
@ -134,6 +134,7 @@ class Reach:
|
|||
def copy(self, index_list: List[int]):
|
||||
self.__list_copied_profiles.clear()
|
||||
index_list = list(set(index_list)) # delete duplicate index
|
||||
|
||||
for index in index_list:
|
||||
try:
|
||||
self.__list_copied_profiles.append(deepcopy(self.get_profile_i(index)))
|
||||
|
|
|
|||
|
|
@ -0,0 +1,108 @@
|
|||
#!/usr/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
import copy
|
||||
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
from time import time
|
||||
|
||||
from Model.Geometry import PointXYZ
|
||||
from Model.Geometry.ProfileXYZ import ProfileXYZ
|
||||
from Model.Geometry.vector_1d import Vector1d
|
||||
|
||||
|
||||
def update_station(list_header, list_point_xyz):
|
||||
profile = ProfileXYZ(list_header, list_point_xyz)
|
||||
if profile.nb_points >= 3:
|
||||
return get_station(profile)
|
||||
else:
|
||||
pass
|
||||
|
||||
|
||||
def get_station(profile: ProfileXYZ) -> np.ndarray:
|
||||
"""Projection of the points of the profile on a plane.
|
||||
|
||||
Args:
|
||||
profile: The profile
|
||||
|
||||
Returns:
|
||||
Projection of the points of the profile on a plane.
|
||||
"""
|
||||
if profile.nb_points >= 3:
|
||||
first_named_point = None
|
||||
index_first_named_point = None
|
||||
last_named_point = None
|
||||
|
||||
for index, point in enumerate(profile.points):
|
||||
if point.point_is_named():
|
||||
index_first_named_point = index
|
||||
first_named_point = point
|
||||
break
|
||||
|
||||
for point in profile.points[::-1]:
|
||||
if point.point_is_named():
|
||||
last_named_point = point
|
||||
break
|
||||
|
||||
station = [] # abscisse en travers
|
||||
constant = 0.0 # constante pour décaler l'origine de l'ascisse en travers caluculée.
|
||||
|
||||
if (first_named_point is not None) and (last_named_point is not None):
|
||||
if first_named_point != last_named_point and first_named_point.x != last_named_point.x:
|
||||
vector = Vector1d(first_named_point, last_named_point)
|
||||
normalized_direction_vec = vector.normalized_direction_vector()
|
||||
else:
|
||||
vector = Vector1d(_first_point_not_nan(profile), _last_point_not_nan(profile))
|
||||
normalized_direction_vec = vector.normalized_direction_vector()
|
||||
|
||||
for point in profile.points:
|
||||
xi = point.x - first_named_point.x
|
||||
yi = point.y - first_named_point.y
|
||||
station_i = normalized_direction_vec[0] * xi + normalized_direction_vec[1] * yi
|
||||
station.append(station_i)
|
||||
|
||||
station = np.array(station)
|
||||
|
||||
constant = station[index_first_named_point] # pour placer l'origine au premier point nomme.
|
||||
elif first_named_point is None:
|
||||
vector = Vector1d(_first_point_not_nan(profile), _last_point_not_nan(profile))
|
||||
normalized_direction_vec = vector.normalized_direction_vector()
|
||||
|
||||
for point in profile.points:
|
||||
xi = point.x - _first_point_not_nan(profile).x
|
||||
yi = point.y - _first_point_not_nan(profile).y
|
||||
station_i = normalized_direction_vec[0] * xi + normalized_direction_vec[1] * yi
|
||||
station.append(station_i)
|
||||
|
||||
station = np.array(station)
|
||||
index_profile_z_min = np.where(np.array(profile.z) == profile.z_min)[0][0]
|
||||
constant = station[index_profile_z_min] # pour placer l'origine au fond ie à la cote minimale
|
||||
# z_min du profil.
|
||||
station = station - constant
|
||||
|
||||
return station
|
||||
else:
|
||||
return np.array(np.nan)
|
||||
|
||||
def _point_is_nan(point: PointXYZ):
|
||||
return pd.isna(point.x) or pd.isna(point.y) or pd.isna(point.z)
|
||||
|
||||
def _first_point_not_nan(profile: ProfileXYZ):
|
||||
first_point_not_nan = profile.points[0]
|
||||
|
||||
for point in profile.points:
|
||||
if not _point_is_nan(point):
|
||||
first_point_not_nan = point
|
||||
break
|
||||
|
||||
return first_point_not_nan
|
||||
|
||||
def _last_point_not_nan(profile: ProfileXYZ):
|
||||
last_point = profile.points[-1]
|
||||
|
||||
for point in profile.points[::-1]:
|
||||
if not _point_is_nan(point):
|
||||
last_point = point
|
||||
break
|
||||
|
||||
return last_point
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
import numpy as np
|
||||
from Model.Geometry.PointXYZ import PointXYZ
|
||||
|
||||
|
||||
class Vector1d:
|
||||
def __init__(self, a: PointXYZ, b: PointXYZ):
|
||||
self.A = a
|
||||
self.B = b
|
||||
|
||||
def __repr__(self):
|
||||
return "vecteur AB = ({}, {}, {})".format(
|
||||
self.B.x - self.A.x,
|
||||
self.B.y - self.A.y,
|
||||
self.B.z - self.A.z
|
||||
)
|
||||
|
||||
def vector1d(self):
|
||||
return np.array([
|
||||
self.B.x - self.A.x,
|
||||
self.B.y - self.A.y,
|
||||
self.B.z - self.A.z
|
||||
])
|
||||
|
||||
def direction_vector(self):
|
||||
return np.array([
|
||||
self.B.x - self.A.x,
|
||||
self.B.y - self.A.y,
|
||||
0
|
||||
])
|
||||
|
||||
def norm_vector(self):
|
||||
return np.linalg.norm(self.vector1d())
|
||||
|
||||
def norm_direction_vector(self):
|
||||
return np.linalg.norm(self.direction_vector())
|
||||
|
||||
def normalized_direction_vector(self):
|
||||
return self.direction_vector() / self.norm_direction_vector()
|
||||
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
import os
|
||||
|
||||
from PyQt5.QtCore import Qt
|
||||
|
||||
from PyQt5.QtWidgets import (
|
||||
QMainWindow, QApplication, QDesktopWidget,
|
||||
QMdiArea, QMdiSubWindow, QDialog,
|
||||
|
|
@ -25,12 +27,12 @@ class ASubWindow(QDialog):
|
|||
self.name = name
|
||||
self.parent = parent
|
||||
self.parent.sub_win_add(name, self)
|
||||
self.fixed_size()
|
||||
# self.fixed_size()
|
||||
|
||||
def fixed_size(self):
|
||||
width = self.frameGeometry().width()
|
||||
height = self.frameGeometry().height()
|
||||
# self.setFixedSize(width, height)
|
||||
self.setFixedSize(width, height)
|
||||
|
||||
def closeEvent(self, event):
|
||||
if not self.parent is None:
|
||||
|
|
|
|||
|
|
@ -0,0 +1,330 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
import os.path
|
||||
|
||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
from PyQt5.QtCore import Qt, QSize
|
||||
from PyQt5.QtWidgets import (
|
||||
QTableView, QAbstractItemView, QHeaderView
|
||||
)
|
||||
|
||||
from View.Plot import MplCanvas, navigation_toolbar_2qt
|
||||
|
||||
file_path = os.path.abspath(os.path.dirname(__file__))
|
||||
icon_path = f"{os.path.dirname(os.path.dirname(file_path))}/../../ui/ressources/"
|
||||
|
||||
class Ui_MainWindow(object):
|
||||
def setupUi(self, MainWindowProfile):
|
||||
MainWindowProfile.setObjectName("MainWindowProfile")
|
||||
MainWindowProfile.resize(1089, 699)
|
||||
self.centralwidget = QtWidgets.QWidget(MainWindowProfile)
|
||||
self.centralwidget.setObjectName("centralwidget")
|
||||
self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.centralwidget)
|
||||
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
|
||||
self.splitter = QtWidgets.QSplitter(self.centralwidget)
|
||||
self.splitter.setOrientation(Qt.Horizontal)
|
||||
self.splitter.setObjectName("splitter")
|
||||
self.widget = QtWidgets.QWidget(self.splitter)
|
||||
self.widget.setObjectName("widget")
|
||||
self.verticalLayout_left = QtWidgets.QVBoxLayout(self.widget)
|
||||
self.verticalLayout_left.setContentsMargins(0, 0, 0, 0)
|
||||
self.verticalLayout_left.setObjectName("verticalLayout_left")
|
||||
|
||||
self.horizontalLayout = QtWidgets.QHBoxLayout()
|
||||
self.horizontalLayout.setObjectName("horizontalLayout")
|
||||
|
||||
btn_size = QSize(30, 30)
|
||||
|
||||
self.btn_add = QtWidgets.QPushButton(self.widget)
|
||||
self.btn_add.setMaximumSize(QtCore.QSize(30, 30))
|
||||
self.btn_add.setText("")
|
||||
self.btn_add.setObjectName("btn_add")
|
||||
icon_btn_add = QtGui.QIcon()
|
||||
icon_btn_add.addPixmap(
|
||||
QtGui.QPixmap(f"{icon_path}gtk-add.png"))
|
||||
self.btn_add.setIcon(icon_btn_add)
|
||||
self.btn_add.setIconSize(btn_size)
|
||||
self.horizontalLayout.addWidget(self.btn_add)
|
||||
|
||||
self.btn_delete = QtWidgets.QPushButton(self.widget)
|
||||
self.btn_delete.setMaximumSize(QtCore.QSize(30, 30))
|
||||
self.btn_delete.setText("")
|
||||
self.btn_delete.setObjectName("btn_delete")
|
||||
icon_btn_delete = QtGui.QIcon()
|
||||
icon_btn_delete.addPixmap(
|
||||
QtGui.QPixmap(f"{icon_path}gtk-remove.png"))
|
||||
self.btn_delete.setIcon(icon_btn_delete)
|
||||
self.btn_delete.setIconSize(btn_size)
|
||||
self.horizontalLayout.addWidget(self.btn_delete)
|
||||
|
||||
self.btn_sort_asc_x = QtWidgets.QPushButton(self.widget)
|
||||
self.btn_sort_asc_x.setMaximumSize(QtCore.QSize(30, 30))
|
||||
self.btn_sort_asc_x.setText("")
|
||||
self.btn_sort_asc_x.setObjectName("btn_sort_asc_x")
|
||||
icon_btn_sort_asc_x = QtGui.QIcon()
|
||||
icon_btn_sort_asc_x.addPixmap(
|
||||
QtGui.QPixmap(f"{icon_path}gtk-sort-ascending.png"))
|
||||
self.btn_sort_asc_x.setIcon(icon_btn_sort_asc_x)
|
||||
self.btn_sort_asc_x.setIconSize(btn_size)
|
||||
self.horizontalLayout.addWidget(self.btn_sort_asc_x)
|
||||
|
||||
self.btn_sort_desc_x = QtWidgets.QPushButton(self.widget)
|
||||
self.btn_sort_desc_x.setMaximumSize(QtCore.QSize(30, 30))
|
||||
self.btn_sort_desc_x.setText("")
|
||||
self.btn_sort_desc_x.setObjectName("btn_sort_desc_x")
|
||||
icon_btn_sort_desc_x = QtGui.QIcon()
|
||||
icon_btn_sort_desc_x.addPixmap(
|
||||
QtGui.QPixmap(f"{icon_path}gtk-sort-descending.png"))
|
||||
self.btn_sort_desc_x.setIcon(icon_btn_sort_desc_x)
|
||||
self.btn_sort_desc_x.setIconSize(btn_size)
|
||||
self.horizontalLayout.addWidget(self.btn_sort_desc_x)
|
||||
|
||||
self.btn_sort_asc_y = QtWidgets.QPushButton(self.widget)
|
||||
self.btn_sort_asc_y.setMaximumSize(QtCore.QSize(30, 30))
|
||||
self.btn_sort_asc_y.setText("")
|
||||
self.btn_sort_asc_y.setObjectName("btn_sort_asc_y")
|
||||
icon_btn_sort_asc_y = QtGui.QIcon()
|
||||
icon_btn_sort_asc_y.addPixmap(
|
||||
QtGui.QPixmap(f"{icon_path}gtk-sort-ascending.png"))
|
||||
self.btn_sort_asc_y.setIcon(icon_btn_sort_asc_y)
|
||||
self.btn_sort_asc_y.setIconSize(btn_size)
|
||||
self.horizontalLayout.addWidget(self.btn_sort_asc_y)
|
||||
|
||||
self.btn_sort_desc_y = QtWidgets.QPushButton(self.widget)
|
||||
self.btn_sort_desc_y.setMaximumSize(QtCore.QSize(30, 30))
|
||||
self.btn_sort_desc_y.setText("")
|
||||
self.btn_sort_desc_y.setObjectName("btn_sort_desc_y")
|
||||
icon_btn_sort_desc_y = QtGui.QIcon()
|
||||
icon_btn_sort_desc_y.addPixmap(
|
||||
QtGui.QPixmap(f"{icon_path}gtk-sort-descending.png"))
|
||||
self.btn_sort_desc_y.setIcon(icon_btn_sort_desc_y)
|
||||
self.btn_sort_desc_y.setIconSize(btn_size)
|
||||
self.horizontalLayout.addWidget(self.btn_sort_desc_y)
|
||||
|
||||
self.btn_move_up = QtWidgets.QPushButton(self.widget)
|
||||
self.btn_move_up.setMaximumSize(QtCore.QSize(30, 30))
|
||||
self.btn_move_up.setText("")
|
||||
self.btn_move_up.setObjectName("btn_move_up")
|
||||
icon_btn_move_up = QtGui.QIcon()
|
||||
icon_btn_move_up.addPixmap(
|
||||
QtGui.QPixmap(f"{icon_path}up.png"))
|
||||
self.btn_move_up.setIcon(icon_btn_move_up)
|
||||
self.btn_move_up.setIconSize(btn_size)
|
||||
self.horizontalLayout.addWidget(self.btn_move_up)
|
||||
|
||||
self.btn_move_down = QtWidgets.QPushButton(self.widget)
|
||||
self.btn_move_down.setMaximumSize(QtCore.QSize(30, 30))
|
||||
self.btn_move_down.setText("")
|
||||
self.btn_move_down.setObjectName("btn_move_down")
|
||||
icon_btn_move_down = QtGui.QIcon()
|
||||
icon_btn_move_down.addPixmap(
|
||||
QtGui.QPixmap(f"{icon_path}down.png"))
|
||||
self.btn_move_down.setIcon(icon_btn_move_down)
|
||||
self.btn_move_down.setIconSize(btn_size)
|
||||
self.horizontalLayout.addWidget(self.btn_move_down)
|
||||
|
||||
self.btn_export = QtWidgets.QPushButton(self.widget)
|
||||
self.btn_export.setMaximumSize(QtCore.QSize(30, 30))
|
||||
self.btn_export.setText("")
|
||||
self.btn_export.setObjectName("btn_export")
|
||||
icon_btn_export = QtGui.QIcon()
|
||||
icon_btn_export.addPixmap(
|
||||
QtGui.QPixmap(f"{icon_path}export.png"))
|
||||
self.btn_export.setIcon(icon_btn_export)
|
||||
self.btn_export.setIconSize(btn_size)
|
||||
self.horizontalLayout.addWidget(self.btn_export)
|
||||
|
||||
self.btn_copy = QtWidgets.QPushButton(self.widget)
|
||||
self.btn_copy.setMaximumSize(QtCore.QSize(30, 30))
|
||||
self.btn_copy.setText("")
|
||||
self.btn_copy.setObjectName("btn_copy")
|
||||
icon_btn_copy = QtGui.QIcon()
|
||||
icon_btn_copy.addPixmap(
|
||||
QtGui.QPixmap(f"{icon_path}gtk-copy.png"))
|
||||
self.btn_copy.setIcon(icon_btn_copy)
|
||||
self.btn_copy.setIconSize(btn_size)
|
||||
self.horizontalLayout.addWidget(self.btn_copy)
|
||||
|
||||
self.btn_paste = QtWidgets.QPushButton(self.widget)
|
||||
self.btn_paste.setMaximumSize(QtCore.QSize(30, 30))
|
||||
self.btn_paste.setText("")
|
||||
self.btn_paste.setObjectName("btn_paste")
|
||||
icon_btn_paste = QtGui.QIcon()
|
||||
icon_btn_paste.addPixmap(
|
||||
QtGui.QPixmap(f"{icon_path}gtk-paste.png"))
|
||||
self.btn_paste.setIcon(icon_btn_paste)
|
||||
self.btn_paste.setIconSize(btn_size)
|
||||
self.horizontalLayout.addWidget(self.btn_paste)
|
||||
|
||||
self.btn_check = QtWidgets.QPushButton(self.widget)
|
||||
self.btn_check.setMaximumSize(QtCore.QSize(30, 30))
|
||||
self.btn_check.setText("")
|
||||
self.btn_check.setObjectName("btn_check")
|
||||
icon_btn_check = QtGui.QIcon()
|
||||
icon_btn_check.addPixmap(
|
||||
QtGui.QPixmap(f"{icon_path}gtk-apply.png"))
|
||||
self.btn_check.setIcon(icon_btn_check)
|
||||
self.btn_check.setIconSize(btn_size)
|
||||
self.horizontalLayout.addWidget(self.btn_check)
|
||||
|
||||
self.btn_go_back = QtWidgets.QPushButton(self.widget)
|
||||
self.btn_go_back.setMaximumSize(QtCore.QSize(30, 30))
|
||||
self.btn_go_back.setText("")
|
||||
self.btn_go_back.setObjectName("btn_go_back")
|
||||
icon_btn_go_back = QtGui.QIcon()
|
||||
icon_btn_go_back.addPixmap(
|
||||
QtGui.QPixmap(f"{icon_path}gtk-undo.png"))
|
||||
self.btn_go_back.setIcon(icon_btn_go_back)
|
||||
self.btn_go_back.setIconSize(btn_size)
|
||||
self.horizontalLayout.addWidget(self.btn_go_back)
|
||||
|
||||
self.btn_reset = QtWidgets.QPushButton(self.widget)
|
||||
self.btn_reset.setMaximumSize(QtCore.QSize(30, 30))
|
||||
self.btn_reset.setText("")
|
||||
self.btn_reset.setObjectName("btn_reset")
|
||||
icon_btn_reset = QtGui.QIcon()
|
||||
icon_btn_reset.addPixmap(
|
||||
QtGui.QPixmap(f"{icon_path}cancel.png"))
|
||||
self.btn_reset.setIcon(icon_btn_reset)
|
||||
self.btn_reset.setIconSize(btn_size)
|
||||
self.horizontalLayout.addWidget(self.btn_reset)
|
||||
|
||||
spacerItem = QtWidgets.QSpacerItem(30, 30, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
|
||||
self.horizontalLayout.addItem(spacerItem)
|
||||
|
||||
self.verticalLayout_left.addLayout(self.horizontalLayout)
|
||||
|
||||
self.tableView = QTableView(self.widget)
|
||||
self.tableView.setStyleSheet(" QTableView { border: 1px solid black;\n"
|
||||
" gridline-color: blue;\n"
|
||||
" border-radius: 2px;\n"
|
||||
" border-style: solid;\n"
|
||||
" background-color: #EEF6FC; \n"
|
||||
" selection-background-color: #218ede;\n"
|
||||
" font-size: 11.5px;\n"
|
||||
" font-family: Helvetica\n"
|
||||
"\n"
|
||||
" }")
|
||||
# self.tableView.setSelectionMode(QtWidgets.QAbstractItemView.MultiSelection)
|
||||
# self.tableView.setGridStyle(Qt.SolidLine)
|
||||
self.tableView.setObjectName("tableView")
|
||||
self.tableView.setSelectionBehavior(QAbstractItemView.SelectRows) # permet de sélectionner une ligne entière
|
||||
# self.tableView.verticalHeader().hide() # hide vertical/row headers
|
||||
self.tableView.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustToContents)
|
||||
# self.tableView.setSelectionMode(QAbstractItemView.MultiSelection)
|
||||
# self.tableView.horizontalHeader().setStretchLastSection(True)
|
||||
# self.tableView.setVisible(False)
|
||||
self.tableView.resizeColumnsToContents()
|
||||
self.tableView.resizeRowsToContents()
|
||||
# self.tableView.setVisible(True)
|
||||
# self.tableView.verticalHeader().setSectionResizeMode(QHeaderView.Stretch) # pour que le tableau occupe
|
||||
# toute la zone
|
||||
self.tableView.setAlternatingRowColors(True) # colorie une ligne sur 2
|
||||
self.tableView.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) # ajuster la largeur du tableau
|
||||
# self.tableView.setEditTriggers(QAbstractItemView.DoubleClicked) # met en mode édition en cliquant sur une
|
||||
# ligne https://doc.qt.io/qt-5/qabstractitemview.html#EditTrigger-enum NoEditTriggers, DoubleClicked,
|
||||
# SelectedClicked, CurrentChanged
|
||||
self.verticalLayout_left.addWidget(self.tableView)
|
||||
|
||||
self.widget1 = QtWidgets.QWidget(self.splitter)
|
||||
self.widget1.setObjectName("widget1")
|
||||
|
||||
self.verticalLayout_right = QtWidgets.QVBoxLayout(self.widget1)
|
||||
self.verticalLayout_right.setContentsMargins(0, 0, 0, 0)
|
||||
self.verticalLayout_right.setObjectName("verticalLayout_right")
|
||||
|
||||
self.label_graphic_help = QtWidgets.QLabel(self.widget1)
|
||||
self.label_graphic_help.setMaximumSize(QtCore.QSize(16777215, 25))
|
||||
self.label_graphic_help.setBaseSize(QtCore.QSize(0, 30))
|
||||
self.label_graphic_help.setStyleSheet(
|
||||
"QLabel { border: 1px solid blue;\n"
|
||||
" gridline-color: blue;\n"
|
||||
" border-radius: 3px;\n"
|
||||
" border-style: solid;\n"
|
||||
" background-color: #EEF6FC; \n"
|
||||
" selection-background-color: black;\n"
|
||||
" font-size: 11px;\n"
|
||||
" font-family: Helvetica\n"
|
||||
"}"
|
||||
)
|
||||
self.label_graphic_help.setObjectName("label_graphic_help")
|
||||
self.verticalLayout_right.addWidget(self.label_graphic_help)
|
||||
|
||||
# self.graphicsView = QtWidgets.QGraphicsView(self.widget1)
|
||||
# self.graphicsView.setObjectName("graphicsView")
|
||||
# self.verticalLayout_right.addWidget(self.graphicsView)
|
||||
|
||||
self.my_canvas = MplCanvas.MplCanvas(width=5, height=4,
|
||||
dpi=100)
|
||||
self.my_canvas.setObjectName("my_canvas")
|
||||
|
||||
self.my_toolbar = navigation_toolbar_2qt.PamHyrNavigationToolbar2QT(self.my_canvas, self.widget1)
|
||||
self.my_toolbar.setStyleSheet(
|
||||
"QToolBar{ border: 1px solid darkGray;\n"
|
||||
" gridline-color: blue;\n"
|
||||
" border-radius: 4px;\n"
|
||||
" border-style: solid;\n"
|
||||
" background-color: #EEF6FC; \n"
|
||||
" selection-background-color: #218ede;\n"
|
||||
" font-size: 12px;\n"
|
||||
" font-family: Helvetica\n"
|
||||
"\n"
|
||||
" }"
|
||||
)
|
||||
|
||||
self.verticalLayout_right.addWidget(self.my_toolbar)
|
||||
self.verticalLayout_right.addWidget(self.my_canvas)
|
||||
self.horizontalLayout_2.addWidget(self.splitter)
|
||||
|
||||
MainWindowProfile.setCentralWidget(self.centralwidget)
|
||||
|
||||
self.menubar = QtWidgets.QMenuBar(MainWindowProfile)
|
||||
self.menubar.setGeometry(QtCore.QRect(0, 0, 1089, 20))
|
||||
self.menubar.setObjectName("menubar")
|
||||
MainWindowProfile.setMenuBar(self.menubar)
|
||||
self.statusbar = QtWidgets.QStatusBar(MainWindowProfile)
|
||||
self.statusbar.setObjectName("statusbar")
|
||||
MainWindowProfile.setStatusBar(self.statusbar)
|
||||
|
||||
self.retranslateUi(MainWindowProfile)
|
||||
QtCore.QMetaObject.connectSlotsByName(MainWindowProfile)
|
||||
|
||||
def retranslateUi(self, MainWindow):
|
||||
_translate = QtCore.QCoreApplication.translate
|
||||
MainWindow.setWindowTitle(_translate("MainWindowProfile", "MainWindowProfile"))
|
||||
self.btn_add.setToolTip(_translate("MainWindowProfile", "Insérer un point"))
|
||||
self.btn_delete.setToolTip(
|
||||
_translate("MainWindowProfile", "Supprimer le/les point(s) sélectionnés"))
|
||||
self.btn_sort_asc_x.setToolTip(
|
||||
_translate("MainWindowProfile", "Trier les points par ordre croissant de X"))
|
||||
self.btn_sort_desc_x.setToolTip(
|
||||
_translate("MainWindowProfile", "Trier les points par ordre décroissant de X"))
|
||||
self.btn_sort_asc_y.setToolTip(_translate("MainWindowProfile",
|
||||
"Trier les points par ordre croissant de Y"
|
||||
))
|
||||
self.btn_sort_desc_y.setToolTip(_translate("MainWindowProfile",
|
||||
"Trier les points par ordre décroissant de Y"))
|
||||
self.btn_move_up.setToolTip(_translate("MainWindowProfile",
|
||||
"Décaler le point sélectionné vers le haut"))
|
||||
self.btn_move_down.setToolTip(_translate("MainWindowProfile",
|
||||
"Décaler le point sélectionné vers le bas"))
|
||||
self.btn_export.setToolTip(_translate("MainWindowProfile",
|
||||
"Exporter (dans un fichier) les points du profil au format tabulé"))
|
||||
self.btn_copy.setToolTip(
|
||||
_translate("MainWindowProfile", "Copier la sélection au format tabulé"))
|
||||
self.btn_paste.setToolTip(_translate("MainWindowProfile",
|
||||
"Coller la sélection depuis le presse-papier au format tabulé"))
|
||||
self.btn_check.setToolTip(_translate("MainWindowProfile",
|
||||
"Vérifier la validité de la saisie et garder ou pas les modifications "
|
||||
"apportées"))
|
||||
self.btn_go_back.setToolTip(_translate("MainWindowProfile",
|
||||
"Annuler toutes les modifications depuis la dernière validation"))
|
||||
self.btn_reset.setToolTip(_translate("MainWindowProfile",
|
||||
"Annuler toutes les modifications et revenir à l\'état initial"))
|
||||
self.label_graphic_help.setToolTip(_translate("MainWindowProfile",
|
||||
"Ligne d'eau : \n \tZ : Cote (m) \n \tA : Aire mouillée ("
|
||||
"m\u00B2) \n \tp : "
|
||||
"Périmètre mouillé (m) \n \tL : Largeur au miroir (m)"))
|
||||
self.label_graphic_help.setText(
|
||||
_translate("MainWindowProfile", "\'Maj + Clic\' : Ligne d\'eau & \'Ctrl + Clic\' : "
|
||||
"Sélectionner des points"))
|
||||
|
|
@ -0,0 +1,425 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
import sys
|
||||
import os.path
|
||||
|
||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
from PyQt5.QtCore import QSize, Qt
|
||||
from PyQt5.QtWidgets import (
|
||||
QAbstractItemView, QHeaderView
|
||||
)
|
||||
|
||||
from View.Plot import (
|
||||
MplCanvas, navigation_toolbar_2qt
|
||||
)
|
||||
|
||||
file_path = os.path.abspath(os.path.dirname(__file__))
|
||||
icon_path = f"{os.path.dirname(os.path.dirname(file_path))}/../../ui/resources/"
|
||||
|
||||
class Ui_MainWindow(object):
|
||||
def setupUi(self, MainWindow_reach):
|
||||
MainWindow_reach.setObjectName("MainWindow_reach")
|
||||
MainWindow_reach.resize(1400, 800)
|
||||
self.centralwidget = QtWidgets.QWidget(MainWindow_reach)
|
||||
self.centralwidget.setObjectName("centralwidget")
|
||||
self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.centralwidget)
|
||||
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
|
||||
self.splitter_3 = QtWidgets.QSplitter(self.centralwidget)
|
||||
self.splitter_3.setOrientation(Qt.Horizontal)
|
||||
self.splitter_3.setObjectName("splitter_3")
|
||||
self.widget = QtWidgets.QWidget(self.splitter_3)
|
||||
self.widget.setObjectName("widget")
|
||||
self.verticalLayout = QtWidgets.QVBoxLayout(self.widget)
|
||||
self.verticalLayout.setContentsMargins(0, 0, 0, 0)
|
||||
self.verticalLayout.setObjectName("verticalLayout")
|
||||
self.horizontalLayout = QtWidgets.QHBoxLayout()
|
||||
self.horizontalLayout.setObjectName("horizontalLayout")
|
||||
|
||||
self.label_section_order = QtWidgets.QLabel(self.widget)
|
||||
self.label_section_order.setLayoutDirection(Qt.LeftToRight)
|
||||
self.label_section_order.setObjectName("label_section_order")
|
||||
self.label_section_order.setStyleSheet(
|
||||
"QLabel{ border: 1px solid darkGray;\n"
|
||||
" gridline-color: gray;\n"
|
||||
" border-radius: 1px;\n"
|
||||
" border-style: solid;\n"
|
||||
" background-color: ; \n"
|
||||
" selection-background-color: #218ede;\n"
|
||||
" font-size: 12px;\n"
|
||||
" font-family: Helvetica\n"
|
||||
"\n"
|
||||
" }"
|
||||
)
|
||||
self.verticalLayout.addWidget(self.label_section_order)
|
||||
btn_size = QSize(30, 30)
|
||||
self.btn_open = QtWidgets.QPushButton(self.widget)
|
||||
self.btn_open.setMaximumSize(QtCore.QSize(30, 30))
|
||||
self.btn_open.setObjectName("btn_open")
|
||||
icon_btn_open = QtGui.QIcon()
|
||||
icon_btn_open.addPixmap(
|
||||
QtGui.QPixmap(f"{icon_path}open.png"))
|
||||
self.btn_open.setIcon(icon_btn_open)
|
||||
self.btn_open.setIconSize(btn_size)
|
||||
self.horizontalLayout.addWidget(self.btn_open)
|
||||
|
||||
self.btn_add = QtWidgets.QPushButton(self.widget)
|
||||
self.btn_add.setMaximumSize(QtCore.QSize(30, 30))
|
||||
self.btn_add.setObjectName("btn_add")
|
||||
icon_btn_add = QtGui.QIcon()
|
||||
icon_btn_add.addPixmap(
|
||||
QtGui.QPixmap(f"{icon_path}gtk_add.png"))
|
||||
self.btn_add.setIcon(icon_btn_add)
|
||||
self.btn_add.setIconSize(btn_size)
|
||||
self.horizontalLayout.addWidget(self.btn_add)
|
||||
|
||||
self.btn_delete = QtWidgets.QPushButton(self.widget)
|
||||
self.btn_delete.setMaximumSize(QtCore.QSize(30, 30))
|
||||
self.btn_delete.setObjectName("btn_delete")
|
||||
icon_btn_delete = QtGui.QIcon()
|
||||
icon_btn_delete.addPixmap(
|
||||
QtGui.QPixmap(f"{icon_path}gtk-remove.png"))
|
||||
self.btn_delete.setIcon(icon_btn_delete)
|
||||
self.btn_delete.setIconSize(btn_size)
|
||||
self.horizontalLayout.addWidget(self.btn_delete)
|
||||
|
||||
self.btn_edit = QtWidgets.QPushButton(self.widget)
|
||||
self.btn_edit.setMaximumSize(QtCore.QSize(30, 30))
|
||||
self.btn_edit.setObjectName("btn_edit")
|
||||
icon_btn_edit = QtGui.QIcon()
|
||||
icon_btn_edit.addPixmap(
|
||||
QtGui.QPixmap(f"{icon_path}gnome-stock-edit.png"))
|
||||
self.btn_edit.setIcon(icon_btn_edit)
|
||||
self.btn_edit.setIconSize(btn_size)
|
||||
self.horizontalLayout.addWidget(self.btn_edit)
|
||||
|
||||
self.btn_copy_selected_profile = QtWidgets.QPushButton(self.widget)
|
||||
self.btn_copy_selected_profile.setMaximumSize(QtCore.QSize(30, 30))
|
||||
self.btn_copy_selected_profile.setObjectName("btn_copy_selected_profile")
|
||||
icon_btn_copy_selected_profile = QtGui.QIcon()
|
||||
icon_btn_copy_selected_profile.addPixmap(
|
||||
QtGui.QPixmap(f"{icon_path}gtk-copy.png"))
|
||||
self.btn_copy_selected_profile.setIcon(icon_btn_copy_selected_profile)
|
||||
self.btn_copy_selected_profile.setIconSize(btn_size)
|
||||
self.horizontalLayout.addWidget(self.btn_copy_selected_profile)
|
||||
|
||||
self.btn_paste_selected_profile = QtWidgets.QPushButton(self.widget)
|
||||
self.btn_paste_selected_profile.setMaximumSize(QtCore.QSize(30, 30))
|
||||
self.btn_paste_selected_profile.setObjectName("btn_paste_selected_profile")
|
||||
icon_btn_paste_selected_profile = QtGui.QIcon()
|
||||
icon_btn_paste_selected_profile.addPixmap(
|
||||
QtGui.QPixmap(f"{icon_path}gtk-paste.png"))
|
||||
self.btn_paste_selected_profile.setIcon(icon_btn_paste_selected_profile)
|
||||
self.btn_paste_selected_profile.setIconSize(btn_size)
|
||||
self.horizontalLayout.addWidget(self.btn_paste_selected_profile)
|
||||
|
||||
self.btn_duplicate_selected_profile = QtWidgets.QPushButton(self.widget)
|
||||
self.btn_duplicate_selected_profile.setMaximumSize(QtCore.QSize(30, 30))
|
||||
self.btn_duplicate_selected_profile.setObjectName("btn_duplicate_selected_profile")
|
||||
icon_btn_duplicate_selected_profile = QtGui.QIcon()
|
||||
icon_btn_duplicate_selected_profile.addPixmap(
|
||||
QtGui.QPixmap(f"{icon_path}gtk-dnd-multiple.png"))
|
||||
self.btn_duplicate_selected_profile.setIcon(icon_btn_duplicate_selected_profile)
|
||||
self.btn_duplicate_selected_profile.setIconSize(btn_size)
|
||||
self.horizontalLayout.addWidget(self.btn_duplicate_selected_profile)
|
||||
|
||||
self.btn_sort_asc = QtWidgets.QPushButton(self.widget)
|
||||
self.btn_sort_asc.setMaximumSize(QtCore.QSize(30, 30))
|
||||
self.btn_sort_asc.setText("")
|
||||
self.btn_sort_asc.setObjectName("btn_sort_asc")
|
||||
icon_btn_sort_asc = QtGui.QIcon()
|
||||
icon_btn_sort_asc.addPixmap(
|
||||
QtGui.QPixmap(f"{icon_path}gtk-sort-ascending.png"))
|
||||
self.btn_sort_asc.setIcon(icon_btn_sort_asc)
|
||||
self.btn_sort_asc.setIconSize(btn_size)
|
||||
self.horizontalLayout.addWidget(self.btn_sort_asc)
|
||||
|
||||
self.btn_sort_desc = QtWidgets.QPushButton(self.widget)
|
||||
self.btn_sort_desc.setMaximumSize(QtCore.QSize(30, 30))
|
||||
self.btn_sort_desc.setText("")
|
||||
self.btn_sort_desc.setObjectName("btn_sort_desc")
|
||||
icon_btn_sort_desc = QtGui.QIcon()
|
||||
icon_btn_sort_desc.addPixmap(
|
||||
QtGui.QPixmap(f"{icon_path}gtk-sort-descending.png"))
|
||||
self.btn_sort_desc.setIcon(icon_btn_sort_desc)
|
||||
self.btn_sort_desc.setIconSize(btn_size)
|
||||
self.horizontalLayout.addWidget(self.btn_sort_desc)
|
||||
|
||||
self.btn_move_up = QtWidgets.QPushButton(self.widget)
|
||||
self.btn_move_up.setMaximumSize(QtCore.QSize(30, 30))
|
||||
self.btn_move_up.setText("")
|
||||
self.btn_move_up.setObjectName("btn_move_up")
|
||||
icon_btn_move_up = QtGui.QIcon()
|
||||
icon_btn_move_up.addPixmap(
|
||||
QtGui.QPixmap(f"{icon_path}up.png"))
|
||||
self.btn_move_up.setIcon(icon_btn_move_up)
|
||||
self.btn_move_up.setIconSize(btn_size)
|
||||
self.horizontalLayout.addWidget(self.btn_move_up)
|
||||
|
||||
self.btn_move_down = QtWidgets.QPushButton(self.widget)
|
||||
self.btn_move_down.setMaximumSize(QtCore.QSize(30, 30))
|
||||
self.btn_move_down.setText("")
|
||||
self.btn_move_down.setObjectName("btn_move_down")
|
||||
icon_btn_move_down = QtGui.QIcon()
|
||||
icon_btn_move_down.addPixmap(
|
||||
QtGui.QPixmap(f"{icon_path}down.png"))
|
||||
self.btn_move_down.setIcon(icon_btn_move_down)
|
||||
self.btn_move_down.setIconSize(btn_size)
|
||||
self.horizontalLayout.addWidget(self.btn_move_down)
|
||||
|
||||
self.btn_end_editing = QtWidgets.QPushButton(self.widget)
|
||||
self.btn_end_editing.setMaximumSize(QtCore.QSize(30, 30))
|
||||
self.btn_end_editing.setText("")
|
||||
self.btn_end_editing.setObjectName("btn_end_editing")
|
||||
icon_btn_save = QtGui.QIcon()
|
||||
icon_btn_save.addPixmap(
|
||||
QtGui.QPixmap(f"{icon_path}gtk-apply.png"))
|
||||
self.btn_end_editing.setIcon(icon_btn_save)
|
||||
self.btn_end_editing.setIconSize(btn_size)
|
||||
self.horizontalLayout.addWidget(self.btn_end_editing)
|
||||
|
||||
spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
|
||||
self.horizontalLayout.addItem(spacerItem)
|
||||
self.verticalLayout.addLayout(self.horizontalLayout)
|
||||
self.tableView = QtWidgets.QTableView(self.widget)
|
||||
self.tableView.setObjectName("tableView")
|
||||
self.verticalLayout.addWidget(self.tableView)
|
||||
self.tableView.setSelectionBehavior(QAbstractItemView.SelectRows) # permet de sélectionner une ligne entière
|
||||
self.tableView.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) # ajuster la largeur du tableau
|
||||
self.tableView.setAlternatingRowColors(True) # colorie une ligne sur 2
|
||||
self.tableView.verticalHeader().hide() # hide vertical/row headers
|
||||
self.tableView.setStyleSheet(
|
||||
" QTableView { border: 1px solid black;\n"
|
||||
" gridline-color: blue;\n"
|
||||
" border-radius: 2px;\n"
|
||||
" border-style: solid;\n"
|
||||
" background-color: #EEF6FC; \n"
|
||||
" selection-background-color: #218ede;\n"
|
||||
" font-size: 12px;\n"
|
||||
" font-family: Helvetica\n"
|
||||
"\n"
|
||||
" }"
|
||||
)
|
||||
self.tableView.resizeColumnsToContents()
|
||||
self.tableView.resizeRowsToContents()
|
||||
|
||||
self.widget1 = QtWidgets.QWidget(self.splitter_3)
|
||||
self.widget1.setObjectName("widget1")
|
||||
self.gridLayout = QtWidgets.QGridLayout(self.widget1)
|
||||
self.gridLayout.setContentsMargins(0, 0, 0, 0)
|
||||
self.gridLayout.setObjectName("gridLayout")
|
||||
self.splitter_2 = QtWidgets.QSplitter(self.widget1)
|
||||
self.splitter_2.setOrientation(Qt.Vertical)
|
||||
self.splitter_2.setObjectName("splitter_2")
|
||||
self.splitter = QtWidgets.QSplitter(self.splitter_2)
|
||||
self.splitter.setOrientation(Qt.Horizontal)
|
||||
self.splitter.setObjectName("splitter")
|
||||
self.verticalLayoutWidget_3 = QtWidgets.QWidget(self.splitter)
|
||||
self.verticalLayoutWidget_3.setObjectName("verticalLayoutWidget_3")
|
||||
self.verticalLayout_canvas_1 = QtWidgets.QVBoxLayout(self.verticalLayoutWidget_3)
|
||||
self.verticalLayout_canvas_1.setContentsMargins(0, 0, 0, 0)
|
||||
self.verticalLayout_canvas_1.setObjectName("verticalLayout_canvas_1")
|
||||
self.canvas_1 = MplCanvas.MplCanvas(width=5, height=4,
|
||||
dpi=100) # QtWidgets.QGraphicsView(self.verticalLayoutWidget_3)
|
||||
|
||||
self.canvas_1.setObjectName("canvas_1")
|
||||
|
||||
self.toolbar_1 = navigation_toolbar_2qt.PamHyrNavigationToolbar2QT(self.canvas_1, self.centralwidget)
|
||||
self.toolbar_1.setStyleSheet("QToolBar{ border: 1px solid darkGray;\n"
|
||||
" gridline-color: blue;\n"
|
||||
" border-radius: 4px;\n"
|
||||
" border-style: solid;\n"
|
||||
" background-color: #EEF6FC; \n"
|
||||
" selection-background-color: #218ede;\n"
|
||||
" font-size: 12px;\n"
|
||||
" font-family: Helvetica\n"
|
||||
"\n"
|
||||
" }")
|
||||
|
||||
self.verticalLayout_canvas_1.addWidget(self.toolbar_1)
|
||||
|
||||
self.verticalLayout_canvas_1.addWidget(self.canvas_1)
|
||||
self.verticalLayoutWidget_2 = QtWidgets.QWidget(self.splitter)
|
||||
self.verticalLayoutWidget_2.setObjectName("verticalLayoutWidget_2")
|
||||
self.verticalLayout_canvas_2 = QtWidgets.QVBoxLayout(self.verticalLayoutWidget_2)
|
||||
self.verticalLayout_canvas_2.setContentsMargins(0, 0, 0, 0)
|
||||
self.verticalLayout_canvas_2.setObjectName("verticalLayout_canvas_2")
|
||||
self.canvas_2 = MplCanvas.MplCanvas(width=5, height=4,
|
||||
dpi=100) # QtWidgets.QGraphicsView(self.verticalLayoutWidget_2)
|
||||
# self.canvas_2.setMouseTracking(False)
|
||||
self.canvas_2.setObjectName("canvas_2")
|
||||
|
||||
self.toolbar_2 = navigation_toolbar_2qt.PamHyrNavigationToolbar2QT(self.canvas_2, self.centralwidget)
|
||||
self.toolbar_2.setStyleSheet(
|
||||
"QToolBar{ border: 1px solid darkGray;\n"
|
||||
" gridline-color: blue;\n"
|
||||
" border-radius: 4px;\n"
|
||||
" border-style: solid;\n"
|
||||
" background-color: #EEF6FC; \n"
|
||||
" selection-background-color: #218ede;\n"
|
||||
" font-size: 12px;\n"
|
||||
" font-family: Helvetica\n"
|
||||
"\n"
|
||||
" }"
|
||||
)
|
||||
# self.frame_toolbar.addWidget(self.toolbar)
|
||||
self.verticalLayout_canvas_2.addWidget(self.toolbar_2)
|
||||
self.verticalLayout_canvas_2.addWidget(self.canvas_2)
|
||||
self.verticalLayoutWidget = QtWidgets.QWidget(self.splitter_2)
|
||||
self.verticalLayoutWidget.setObjectName("verticalLayoutWidget")
|
||||
self.verticalLayout_canvas_3 = QtWidgets.QVBoxLayout(self.verticalLayoutWidget)
|
||||
self.verticalLayout_canvas_3.setContentsMargins(0, 0, 0, 0)
|
||||
self.verticalLayout_canvas_3.setObjectName("verticalLayout_canvas_3")
|
||||
self.canvas_3 = MplCanvas.MplCanvas(width=5, height=4,
|
||||
dpi=100) # QtWidgets.QGraphicsView(self.verticalLayoutWidget)
|
||||
self.canvas_3.setObjectName("canvas_3")
|
||||
|
||||
self.toolbar_3 = navigation_toolbar_2qt.PamHyrNavigationToolbar2QT(self.canvas_3, self.centralwidget)
|
||||
self.toolbar_3.setStyleSheet(
|
||||
"QToolBar{ border: 1px solid darkGray;\n"
|
||||
" gridline-color: blue;\n"
|
||||
" border-radius: 4px;\n"
|
||||
" border-style: solid;\n"
|
||||
" background-color: #EEF6FC; \n"
|
||||
" selection-background-color: #218ede;\n"
|
||||
" font-size: 12px;\n"
|
||||
" font-family: Helvetica\n"
|
||||
"\n"
|
||||
" }"
|
||||
)
|
||||
# self.frame_toolbar.addWidget(self.toolbar)
|
||||
self.verticalLayout_canvas_3.addWidget(self.toolbar_3)
|
||||
# self.verticalLayout_canvas_3.addWidget(self.canvas_3)
|
||||
# from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
|
||||
# import matplotlib.pyplot as plt
|
||||
# self.figure = plt.figure()
|
||||
# self.canvas_3 = FigureCanvas(self.figure)
|
||||
self.verticalLayout_canvas_3.addWidget(self.canvas_3)
|
||||
|
||||
self.gridLayout.addWidget(self.splitter_2, 0, 0, 3, 3)
|
||||
self.verticalSlider = QtWidgets.QSlider(self.widget1)
|
||||
self.verticalSlider.setMinimumSize(QtCore.QSize(30, 0))
|
||||
self.verticalSlider.setOrientation(Qt.Vertical)
|
||||
self.verticalSlider.setInvertedAppearance(True)
|
||||
self.verticalSlider.setInvertedControls(False)
|
||||
self.verticalSlider.setObjectName("verticalSlider")
|
||||
self.gridLayout.addWidget(self.verticalSlider, 0, 3, 1, 1)
|
||||
|
||||
self.btn_slider_up = QtWidgets.QPushButton(self.widget1)
|
||||
self.btn_slider_up.setMaximumSize(QtCore.QSize(30, 30))
|
||||
self.btn_slider_up.setObjectName("btn_slider_up")
|
||||
icon_btn_slider_up = QtGui.QIcon()
|
||||
icon_btn_slider_up.addPixmap(
|
||||
QtGui.QPixmap(f"{icon_path}go-up2.png"))
|
||||
self.btn_slider_up.setIcon(icon_btn_slider_up)
|
||||
self.btn_slider_up.setIconSize(btn_size)
|
||||
self.gridLayout.addWidget(self.btn_slider_up, 1, 3, 1, 1)
|
||||
|
||||
self.btn_slider_down = QtWidgets.QPushButton(self.widget1)
|
||||
self.btn_slider_down.setMaximumSize(QtCore.QSize(30, 30))
|
||||
self.btn_slider_down.setObjectName("btn_slider_down")
|
||||
icon_btn_slider_down = QtGui.QIcon()
|
||||
icon_btn_slider_down.addPixmap(
|
||||
QtGui.QPixmap(f"{icon_path}go-down1.png"))
|
||||
self.btn_slider_down.setIcon(icon_btn_slider_down)
|
||||
self.btn_slider_down.setIconSize(btn_size)
|
||||
self.gridLayout.addWidget(self.btn_slider_down, 2, 3, 1, 1)
|
||||
|
||||
self.vertical_slider_label = QtWidgets.QLabel(self.widget1)
|
||||
# self.vertical_slider_label.setLayoutDirection(Qt.RightToLeft)
|
||||
# self.vertical_slider_label.setLayoutDirection(Qt.LeftToRight)
|
||||
self.vertical_slider_label.setObjectName("vertical_slider_label")
|
||||
self.gridLayout.addWidget(self.vertical_slider_label, 3, 2, 2, 1)
|
||||
self.vertical_slider_label.setAlignment(Qt.AlignRight)
|
||||
|
||||
self.btn_slider_go_back = QtWidgets.QPushButton(self.widget1)
|
||||
self.btn_slider_go_back.setMaximumSize(QtCore.QSize(30, 30))
|
||||
self.btn_slider_go_back.setObjectName("btn_slider_go_back")
|
||||
icon_btn_slider_go_back = QtGui.QIcon()
|
||||
icon_btn_slider_go_back.addPixmap(
|
||||
QtGui.QPixmap(f"{icon_path}gtk-go-back.png"))
|
||||
self.btn_slider_go_back.setIcon(icon_btn_slider_go_back)
|
||||
self.btn_slider_go_back.setIconSize(btn_size)
|
||||
self.gridLayout.addWidget(self.btn_slider_go_back, 5, 0, 1, 1)
|
||||
self.btn_slider_go_back.setEnabled(False)
|
||||
|
||||
self.btn_slider_go_forward = QtWidgets.QPushButton(self.widget1)
|
||||
self.btn_slider_go_forward.setMaximumSize(QtCore.QSize(30, 30))
|
||||
self.btn_slider_go_forward.setObjectName("btn_slider_go_forward")
|
||||
icon_btn_slider_go_forward = QtGui.QIcon()
|
||||
icon_btn_slider_go_forward.addPixmap(
|
||||
QtGui.QPixmap(f"{icon_path}gtk-go-forward.png"))
|
||||
self.btn_slider_go_forward.setIcon(icon_btn_slider_go_forward)
|
||||
self.btn_slider_go_forward.setIconSize(btn_size)
|
||||
self.gridLayout.addWidget(self.btn_slider_go_forward, 5, 1, 1, 1)
|
||||
self.btn_slider_go_forward.setEnabled(False)
|
||||
|
||||
self.horizontalSlider = QtWidgets.QSlider(self.widget1)
|
||||
self.horizontalSlider.setMinimumSize(QtCore.QSize(0, 30))
|
||||
self.horizontalSlider.setOrientation(Qt.Horizontal)
|
||||
self.horizontalSlider.setObjectName("horizontalSlider")
|
||||
self.gridLayout.addWidget(self.horizontalSlider, 5, 2, 1, 1)
|
||||
self.horizontalSlider.setEnabled(False)
|
||||
|
||||
self.horizontalLayout_2.addWidget(self.splitter_3)
|
||||
MainWindow_reach.setCentralWidget(self.centralwidget)
|
||||
self.menubar = QtWidgets.QMenuBar(MainWindow_reach)
|
||||
self.menubar.setGeometry(QtCore.QRect(0, 0, 1123, 20))
|
||||
self.menubar.setObjectName("menubar")
|
||||
MainWindow_reach.setMenuBar(self.menubar)
|
||||
self.statusbar = QtWidgets.QStatusBar(MainWindow_reach)
|
||||
self.statusbar.setObjectName("statusbar")
|
||||
MainWindow_reach.setStatusBar(self.statusbar)
|
||||
|
||||
self.retranslateUi(MainWindow_reach)
|
||||
QtCore.QMetaObject.connectSlotsByName(MainWindow_reach)
|
||||
|
||||
def retranslateUi(self, MainWindow_reach):
|
||||
_translate = QtCore.QCoreApplication.translate
|
||||
self.name_reach = ""
|
||||
self.mainwindow_title = _translate("MainWindow_reach", "Jeu de sections du Bief")
|
||||
MainWindow_reach.setWindowTitle(self.mainwindow_title + f"{self.name_reach}")
|
||||
self.text_section_order = _translate("MainWindow_reach", "\nOrdre des sections : "
|
||||
"Amont --> Aval")
|
||||
self.label_section_order.setText(f"{self.text_section_order}")
|
||||
self.vertical_slider_value = ""
|
||||
self.vertical_slider_label.setText(_translate("MainWindow_reach", "Pk = ") + f"{self.vertical_slider_value}")
|
||||
self.btn_open.setToolTip(_translate("MainWindow_reach", " Importer une géométrie"))
|
||||
self.btn_add.setToolTip(_translate("MainWindow_reach", " Nouveau profil"))
|
||||
self.btn_delete.setToolTip(_translate("MainWindow_reach", " Supprimer le profil sélectionné"))
|
||||
self.btn_edit.setToolTip(_translate("MainWindow_reach", " Éditer le profil sélectionné"))
|
||||
self.btn_copy_selected_profile.setToolTip(_translate("MainWindow_reach", " Copier le profil sélectionné"))
|
||||
self.btn_paste_selected_profile.setToolTip(_translate("MainWindow_reach", "Coller le profil en fin de liste ("
|
||||
"penser à modifier le Pk avant de "
|
||||
"trier)"))
|
||||
self.btn_duplicate_selected_profile.setToolTip(
|
||||
_translate("MainWindow_reach", " Dupliquer la section sélectionnée"))
|
||||
self.btn_sort_asc.setToolTip(_translate("MainWindow_reach", " Trier les profils par ordre croissant des Pk"))
|
||||
self.btn_sort_desc.setToolTip(_translate("MainWindow_reach", " Trier les profils par ordre décroissant des Pk"))
|
||||
self.btn_move_up.setToolTip(_translate("MainWindow_reach", " Changer l'ordre des profils (en décalant le "
|
||||
"profil sélectionné vers le haut)"))
|
||||
self.btn_move_down.setToolTip(_translate("MainWindow_reach", " Changer l'ordre des profils (en décalant le "
|
||||
"profil sélectionné vers le bas)"))
|
||||
self.btn_end_editing.setToolTip(_translate("MainWindow_reach", " Terminer l'édition"))
|
||||
self.tableView_header = [_translate("MainWindow_reach", "Nom"), _translate("MainWindow_reach", "Pk (m)"),
|
||||
_translate("MainWindow_reach", "Type")]
|
||||
|
||||
self.toolbar_1._actions["isometric_view"].setShortcut(_translate("MainWindow_reach", "Alt+Z"))
|
||||
self.toolbar_1._actions["isometric_view"].setToolTip(_translate("MainWindow_reach", "Vue isométrique (Alt+Z)"))
|
||||
|
||||
self.toolbar_2._actions["isometric_view"].setShortcut(_translate("MainWindow_reach", "Alt+E"))
|
||||
self.toolbar_2._actions["isometric_view"].setToolTip(_translate("MainWindow_reach", "Vue isométrique (Alt+E)"))
|
||||
|
||||
self.toolbar_3._actions["isometric_view"].setShortcut(_translate("MainWindow_reach", "Alt+R"))
|
||||
self.toolbar_3._actions["isometric_view"].setToolTip(_translate("MainWindow_reach", "Vue isométrique (Alt+R)"))
|
||||
|
||||
self.toolbar_1._actions["non_isometric_view"].setShortcut("Alt+S")
|
||||
self.toolbar_1._actions["non_isometric_view"].setToolTip(
|
||||
_translate("MainWindow_reach", "Vue globale automatique (Alt+S)"))
|
||||
|
||||
self.toolbar_2._actions["non_isometric_view"].setShortcut("Alt+D")
|
||||
self.toolbar_2._actions["non_isometric_view"].setToolTip(
|
||||
_translate("MainWindow_reach", "Vue globale automatique (Alt+D)"))
|
||||
|
||||
self.toolbar_3._actions["non_isometric_view"].setShortcut("Alt+F")
|
||||
self.toolbar_3._actions["non_isometric_view"].setToolTip(
|
||||
_translate("MainWindow_reach", "Vue globale automatique (Alt+F)"))
|
||||
|
|
@ -0,0 +1,422 @@
|
|||
import numpy as np
|
||||
import pandas as pd
|
||||
from PyQt5.QtGui import QFont
|
||||
|
||||
from PyQt5.QtWidgets import QMessageBox
|
||||
from PyQt5 import QtWidgets, QtGui
|
||||
from PyQt5.QtCore import QModelIndex, Qt, QAbstractTableModel, QVariant, QCoreApplication
|
||||
from ProfileXYZ import ProfileXYZ
|
||||
import projection_pointXYZ
|
||||
|
||||
_translate = QCoreApplication.translate
|
||||
|
||||
|
||||
class PandasModelEditable(QAbstractTableModel):
|
||||
def __init__(self, profile: ProfileXYZ, table_header=None):
|
||||
QAbstractTableModel.__init__(self)
|
||||
|
||||
if table_header is None:
|
||||
self.header = ["X (m)", "Y (m)", "Z (m)", _translate("MainWindowProfile", "Nom"),
|
||||
_translate("MainWindowProfile", "Abs en travers (m)")]
|
||||
else:
|
||||
self.header = table_header
|
||||
|
||||
self.profile = profile
|
||||
|
||||
data = pd.DataFrame({
|
||||
self.header[0]: profile.x,
|
||||
self.header[1]: profile.y,
|
||||
self.header[2]: profile.z,
|
||||
self.header[3]: profile.ld,
|
||||
self.header[4]: projection_pointXYZ.get_station(profile)
|
||||
})
|
||||
self._data = data
|
||||
|
||||
def rowCount(self, parent=QModelIndex()):
|
||||
return self._data.shape[0]
|
||||
|
||||
def columnCount(self, parent=QModelIndex()):
|
||||
return self._data.shape[1]
|
||||
|
||||
def data(self, index, role=Qt.DisplayRole):
|
||||
value = self._data.iloc[index.row()][index.column()]
|
||||
if index.isValid():
|
||||
if role == Qt.DisplayRole:
|
||||
if index.column() != 4:
|
||||
if isinstance(value, float):
|
||||
return "%.4f" % value
|
||||
else:
|
||||
if isinstance(value, float):
|
||||
return "%.3f" % value
|
||||
|
||||
return str(self._data.iloc[index.row(), index.column()])
|
||||
|
||||
if role == Qt.TextAlignmentRole:
|
||||
return Qt.AlignHCenter | Qt.AlignVCenter
|
||||
|
||||
if index.column() == 2:
|
||||
if role == Qt.ForegroundRole:
|
||||
if value == min(self._data.iloc[:, index.column()]):
|
||||
return QtGui.QColor("red")
|
||||
elif value == max(self._data.iloc[:, index.column()]):
|
||||
return QtGui.QColor("Blue")
|
||||
|
||||
if role == Qt.ToolTipRole:
|
||||
if value == min(self._data.iloc[:, index.column()]):
|
||||
return _translate("MainWindowProfile", "La cote du fond", "Z minimale")
|
||||
elif value == max(self._data.iloc[:, index.column()]):
|
||||
return _translate("MainWindowProfile", "La cote maximale", "Z maximale")
|
||||
|
||||
if index.column() == 3:
|
||||
if value.strip().upper() in ["RG", "RD"]:
|
||||
if role == Qt.FontRole:
|
||||
font = QFont()
|
||||
font.setBold(True)
|
||||
return font
|
||||
|
||||
if role == Qt.ForegroundRole:
|
||||
return QtGui.QColor("darkRed")
|
||||
|
||||
if role == Qt.ToolTipRole:
|
||||
if value.strip().upper() == "RG":
|
||||
return _translate("MainWindowProfile", "Rive gauche")
|
||||
else:
|
||||
return _translate("MainWindowProfile", "Rive droite")
|
||||
|
||||
if index.column() == 4:
|
||||
if role == Qt.FontRole:
|
||||
font = QFont()
|
||||
font.setBold(True)
|
||||
return font
|
||||
|
||||
if role == Qt.BackgroundRole:
|
||||
return QtGui.QColor("#ededee")
|
||||
|
||||
return QVariant()
|
||||
|
||||
def headerData(self, section, orientation, role=Qt.DisplayRole):
|
||||
if orientation == Qt.Horizontal and role == Qt.DisplayRole:
|
||||
return self.header[section]
|
||||
|
||||
if role == Qt.ToolTipRole and section == 4:
|
||||
return _translate(
|
||||
"MainWindowProfile",
|
||||
"Abscisse en travers calculée en projétant les points"
|
||||
" \nsur le plan défini par les deux points nommés extrêmes "
|
||||
)
|
||||
|
||||
if orientation == Qt.Vertical and role == Qt.DisplayRole:
|
||||
return self._data.index[section] + 1
|
||||
|
||||
return None
|
||||
|
||||
def setData(self, index, value, role=Qt.EditRole):
|
||||
if role == Qt.EditRole:
|
||||
try:
|
||||
if index.column() == 3:
|
||||
self._data.iat[index.row(), index.column()] = str(value)
|
||||
elif index.column() == 0:
|
||||
self._data.iat[index.row(), index.column()] = float(value)
|
||||
elif index.column() == 1:
|
||||
self._data.iat[index.row(), index.column()] = float(value)
|
||||
elif index.column() == 2:
|
||||
self._data.iat[index.row(), index.column()] = float(value)
|
||||
|
||||
self._data.iloc[:, 4] = projection_pointXYZ.update_station(
|
||||
self.header,
|
||||
self._data.values.tolist()
|
||||
)
|
||||
self.dataChanged.emit(index, index)
|
||||
except:
|
||||
print('TODO')
|
||||
self.QMessageBoxCritical(value)
|
||||
|
||||
return True
|
||||
|
||||
self.dataChanged.emit(index, index)
|
||||
self.layoutChanged.emit()
|
||||
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def QMessageBoxCritical(value):
|
||||
msg = QMessageBox()
|
||||
msg.setIcon(QMessageBox.Warning)
|
||||
msg.setText("{} : Valeur saisie incorrecte ".format(value))
|
||||
msg.setInformativeText("Seules les valeurs numériques sont autorisées.")
|
||||
msg.setWindowTitle("Warning ")
|
||||
msg.setStyleSheet("QLabel{min-width:150 px; font-size: 13px;} QPushButton{ width:20px; font-size: 12px};"
|
||||
"background-color: Ligthgray ; color : gray;font-size: 8pt; color: #888a80;")
|
||||
msg.exec_()
|
||||
|
||||
def index(self, row, column, parent=QModelIndex()):
|
||||
if not self.hasIndex(row, column, parent):
|
||||
return QModelIndex()
|
||||
return self.createIndex(row, column, QModelIndex())
|
||||
|
||||
def flags(self, index):
|
||||
return Qt.ItemIsEditable | Qt.ItemIsSelectable | Qt.ItemIsEnabled
|
||||
|
||||
# @QtCore.pyqtSlot()
|
||||
def insertRows(self, row, count, parent=QModelIndex()):
|
||||
self.beginInsertRows(parent, row, row + count - 1)
|
||||
indexes = [str(self.rowCount() + i) for i in range(count)]
|
||||
left = self._data[0:row]
|
||||
mid = pd.DataFrame(index=indexes, columns=self._data.columns)
|
||||
right = self._data[row + count - 1:self.rowCount()]
|
||||
|
||||
self._data = pd.concat([left, mid, right])
|
||||
|
||||
for i in [3]:
|
||||
self._data.iloc[:, i].replace(np.nan, '', inplace=True)
|
||||
|
||||
self._data.reset_index(drop=True, inplace=True)
|
||||
|
||||
try:
|
||||
self._data.iloc[:, 4] = projection_pointXYZ.update_station(
|
||||
self.header,
|
||||
self._data.values.tolist()
|
||||
)
|
||||
except:
|
||||
print("TODO")
|
||||
|
||||
self.endInsertRows()
|
||||
self.layoutChanged.emit()
|
||||
|
||||
# @QtCore.pyqtSlot()
|
||||
def removeRows(self, row, count, parent=QModelIndex()):
|
||||
self.beginRemoveRows(parent, row, row + count + 1)
|
||||
self._data.drop(self._data.index[row], inplace=True)
|
||||
self._data.iloc[:, 4] = projection_pointXYZ.update_station(
|
||||
self.header,
|
||||
self._data.values.tolist()
|
||||
)
|
||||
self.endRemoveRows()
|
||||
self.layoutChanged.emit()
|
||||
|
||||
def remove_rows1(self, row, count, parent=QModelIndex()):
|
||||
self.beginRemoveRows(parent, row, row + count - 1)
|
||||
left = self._data.iloc[0:row]
|
||||
right = self._data.iloc[row + count:self.rowCount()]
|
||||
|
||||
self._data = pd.concat([left, right], axis=0, ignore_index=True)
|
||||
self._data.iloc[:, 4] = projection_pointXYZ.update_station(
|
||||
self.header,
|
||||
self._data.values.tolist()
|
||||
)
|
||||
self.endRemoveRows()
|
||||
self.layoutChanged.emit()
|
||||
|
||||
def remove_rows(self, list_row_selected, parent=QModelIndex()):
|
||||
self.beginRemoveRows(parent, list_row_selected[0], list_row_selected[-1])
|
||||
|
||||
try:
|
||||
self._data.drop(self._data.index[list_row_selected], inplace=True)
|
||||
self._data.reset_index(drop=True, inplace=True)
|
||||
except:
|
||||
print('TODO')
|
||||
try:
|
||||
self._data.iloc[:, 4] = projection_pointXYZ.update_station(
|
||||
self.header,
|
||||
self._data.values.tolist()
|
||||
)
|
||||
except:
|
||||
print("TODO")
|
||||
|
||||
self.endRemoveRows()
|
||||
self.layoutChanged.emit()
|
||||
|
||||
def sort(self, column, order=Qt.AscendingOrder):
|
||||
self.layoutAboutToBeChanged.emit()
|
||||
colname = self._data.columns.tolist()[column]
|
||||
self._data.sort_values(colname, ascending=order == Qt.AscendingOrder, inplace=True)
|
||||
self._data.reset_index(inplace=True, drop=True)
|
||||
|
||||
self._data.iloc[:, 4] = projection_pointXYZ.update_station(
|
||||
self.header,
|
||||
self._data.values.tolist()
|
||||
)
|
||||
self.layoutChanged.emit()
|
||||
|
||||
def moveRowDown(self, row_to_move, parent=QModelIndex()):
|
||||
target = row_to_move + 2
|
||||
self.beginMoveRows(parent, row_to_move, row_to_move, parent, target)
|
||||
block_before_row = self._data.iloc[0:row_to_move]
|
||||
selected_row = self._data.iloc[row_to_move:row_to_move + 1]
|
||||
after_selcted_row = self._data.iloc[row_to_move + 1:row_to_move + 2]
|
||||
block_after_row = self._data.iloc[row_to_move + 2:self.rowCount()]
|
||||
|
||||
self._data = pd.concat([block_before_row, after_selcted_row, selected_row, block_after_row], axis=0)
|
||||
self._data.reset_index(inplace=True, drop=True)
|
||||
|
||||
self.endMoveRows()
|
||||
self.layoutChanged.emit()
|
||||
|
||||
def moveRowUp(self, row_to_move, parent=QModelIndex()):
|
||||
target = row_to_move + 1
|
||||
self.beginMoveRows(parent, row_to_move - 1, row_to_move - 1, parent, target)
|
||||
block_before_row = self._data.iloc[0:row_to_move - 1]
|
||||
before_selected_row = self._data.iloc[row_to_move - 1:row_to_move]
|
||||
selected_row = self._data.iloc[row_to_move:row_to_move + 1]
|
||||
block_after_row = self._data.iloc[row_to_move + 1:self.rowCount()]
|
||||
|
||||
self._data = pd.concat([block_before_row, selected_row, before_selected_row, block_after_row], axis=0)
|
||||
self._data.reset_index(inplace=True, drop=True)
|
||||
|
||||
self.endMoveRows()
|
||||
self.layoutChanged.emit()
|
||||
|
||||
def copyTable(self, start_selection, end_selection):
|
||||
end_selection = self.rowCount()
|
||||
|
||||
self._data.loc[start_selection:end_selection]\
|
||||
.to_clipboard(header=None, index=False, excel=True, sep='\t')
|
||||
|
||||
def insert_df_to_idx(self, idx, df, df_insert):
|
||||
"""
|
||||
Args:
|
||||
idx: is the index position in df where you want to insert new dataframe (df_insert)
|
||||
df: dataframe
|
||||
df_insert: dataframe to insert
|
||||
Returns:
|
||||
The dataframe df with df_insert inserted at index idx.
|
||||
"""
|
||||
return df.iloc[:idx, ].append(df_insert).append(df.iloc[idx:, ]).reset_index(drop=True)
|
||||
|
||||
def pasteTable(self, insertion_index):
|
||||
self.layoutAboutToBeChanged.emit()
|
||||
df = pd.read_clipboard(header=None, skip_blank_lines=True,
|
||||
sep="\t", names=self.header)
|
||||
self._data = self.insert_df_to_idx(insertion_index, self._data, df)
|
||||
|
||||
for i in [3]:
|
||||
self._data.iloc[:, i].replace(np.nan, '', inplace=True)
|
||||
|
||||
self.layoutChanged.emit()
|
||||
self._data.iloc[:, 4] = projection_pointXYZ.update_station(
|
||||
self.header,
|
||||
self._data.values.tolist()
|
||||
)
|
||||
|
||||
@property
|
||||
def model_data(self):
|
||||
return self._data
|
||||
|
||||
@model_data.setter
|
||||
def model_data(self, new_data):
|
||||
self._data = new_data
|
||||
self.layoutChanged.emit()
|
||||
|
||||
@property
|
||||
def x(self):
|
||||
return self._data.iloc[:, 0].tolist()
|
||||
|
||||
@property
|
||||
def y(self):
|
||||
return self._data.iloc[:, 1].tolist()
|
||||
|
||||
@property
|
||||
def z(self):
|
||||
return self._data.iloc[:, 2].tolist()
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
return self._data.iloc[:, 3].tolist()
|
||||
|
||||
def get_data(self):
|
||||
return self._data
|
||||
|
||||
@property
|
||||
def station(self):
|
||||
return self._data.iloc[:, 4].tolist()
|
||||
|
||||
def remove_duplicates_names(self):
|
||||
counter_list = []
|
||||
list_deleted_names = []
|
||||
ind_ind = []
|
||||
|
||||
for ind, name_point in enumerate(self.name):
|
||||
if name_point not in counter_list:
|
||||
counter_list.append(name_point)
|
||||
elif len(name_point.strip()) > 0 and name_point in counter_list:
|
||||
ind_ind.append(ind)
|
||||
|
||||
if name_point not in list_deleted_names:
|
||||
list_deleted_names.append(name_point)
|
||||
|
||||
for ind in ind_ind:
|
||||
self._data.iat[ind, 3] = ""
|
||||
|
||||
def data_contains_nan(self) -> bool:
|
||||
"""
|
||||
Returns:
|
||||
Returns True if the QTableView() contains np.nan
|
||||
"""
|
||||
return self._data.isnull().values.any()
|
||||
|
||||
def delete_empty_rows(self):
|
||||
self.layoutAboutToBeChanged.emit()
|
||||
|
||||
self._data.dropna(inplace=True)
|
||||
self._data.reset_index(drop=True, inplace=True)
|
||||
|
||||
self.layoutChanged.emit()
|
||||
|
||||
def valide_all_changes(self):
|
||||
self.profile.x = self._data.iloc[:, 0]
|
||||
self.profile.y = self._data.iloc[:, 1]
|
||||
self.profile.z = self._data.iloc[:, 2]
|
||||
self.profile.ld = self._data.iloc[:, 3]
|
||||
|
||||
|
||||
class Delegate(QtWidgets.QStyledItemDelegate):
|
||||
def __init__(self, parent=None, setModelDataEvent=None):
|
||||
super(Delegate, self).__init__(parent)
|
||||
self.setModelDataEvent = setModelDataEvent
|
||||
|
||||
def createEditor(self, parent, option, index):
|
||||
"""
|
||||
Args:
|
||||
parent:
|
||||
option:
|
||||
index:
|
||||
Returns:
|
||||
Le widget (éditeur) pour éditer l'item se trouvant à l'index index.
|
||||
"""
|
||||
index.model().data(index, Qt.DisplayRole)
|
||||
return QtWidgets.QLineEdit(parent)
|
||||
|
||||
def setEditorData(self, editor, index):
|
||||
"""
|
||||
Args:
|
||||
editor: l'éditeur
|
||||
index: l'index
|
||||
Returns: permet de transmettre à l'éditeur editor les données à afficher à partir du modèle se trouvant
|
||||
à l'index index.
|
||||
"""
|
||||
value = index.model().data(index, Qt.DisplayRole)
|
||||
editor.setText(str(value))
|
||||
|
||||
def setModelData(self, editor, model, index):
|
||||
"""
|
||||
Args:
|
||||
editor: l'éditeur
|
||||
model: le modèle
|
||||
index: l'index
|
||||
Returns: permet de récupérer les données de l'éditeur et de les stocker à l'intérieur du modèle, à l'index
|
||||
identifié par le paramètre index
|
||||
"""
|
||||
model.setData(index, editor.text())
|
||||
|
||||
if not self.setModelDataEvent is None:
|
||||
self.setModelDataEvent()
|
||||
|
||||
def updateEditorGeometry(self, editor, option, index):
|
||||
"""
|
||||
Args:
|
||||
editor: l'éditeur
|
||||
option:
|
||||
index: l'index
|
||||
Returns: Permet de redimensionner l'éditeur à la bonne taille lorsque la taille de la vue change
|
||||
"""
|
||||
editor.setGeometry(option.rect)
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,934 @@
|
|||
import os
|
||||
import pathlib
|
||||
import sys
|
||||
import csv
|
||||
import time
|
||||
|
||||
from PyQt5 import QtWidgets
|
||||
from PyQt5.QtCore import (
|
||||
QModelIndex, Qt, QSettings, pyqtSlot,
|
||||
QItemSelectionModel, QCoreApplication, QSize
|
||||
)
|
||||
from PyQt5.QtWidgets import (
|
||||
QApplication, QMainWindow, QFileDialog, QCheckBox
|
||||
)
|
||||
|
||||
from View.Geometry.mainwindow_ui_reach import Ui_MainWindow
|
||||
from View.Geometry import qtableview_reach
|
||||
from View.Geometry import window_profileXYZ
|
||||
|
||||
_translate = QCoreApplication.translate
|
||||
|
||||
class GeomatryWindow(ASubWindow):
|
||||
def __init__(self, parent=None):
|
||||
self.parent = parent
|
||||
super(MainReach, self).__init__()
|
||||
|
||||
self.ui = Ui_MainWindow()
|
||||
self.ui.setupUi(self)
|
||||
self.tableView = self.ui.tableView
|
||||
self.tableView_header = self.ui.tableView_header
|
||||
self.model = None
|
||||
self.filename = None
|
||||
self.setup_model()
|
||||
self.setup_connections()
|
||||
|
||||
def setup_connections(self):
|
||||
self.ui.btn_open.clicked.connect(self.open_file_dialog)
|
||||
self.ui.btn_sort_asc.clicked.connect(self.sort_ascending)
|
||||
self.ui.btn_sort_desc.clicked.connect(self.sort_descending)
|
||||
self.ui.btn_move_up.clicked.connect(self.move_row_up)
|
||||
self.ui.btn_move_down.clicked.connect(self.move_row_down)
|
||||
self.ui.btn_end_editing.clicked.connect(self.handleSave)
|
||||
self.ui.btn_add.clicked.connect(self.insert_row)
|
||||
self.ui.btn_delete.clicked.connect(self.delete_row)
|
||||
self.ui.btn_edit.clicked.connect(self.edit_profile)
|
||||
self.ui.verticalSlider.valueChanged.connect(self.changed_slider_value)
|
||||
self.tableView.selectionModel().selectionChanged.connect(self.changed_slider_value)
|
||||
self.ui.btn_slider_up.clicked.connect(self.decrement_value_slider)
|
||||
self.ui.btn_slider_down.clicked.connect(self.increment_value_slider)
|
||||
self.ui.btn_move_up.clicked.connect(self.changed_profile_slot)
|
||||
|
||||
def setup_model(self):
|
||||
self.model = qtableview_reach.PandasModelEditableCreateReach([], self.ui.tableView_header)
|
||||
self.tableView.setModel(self.model)
|
||||
self.tableView.setItemDelegate(qtableview_reach.Delegate())
|
||||
|
||||
def open_file_dialog(self):
|
||||
options = QFileDialog.Options()
|
||||
DEFAULT_DIRECTORY = '/home/'
|
||||
settings = QSettings(QSettings.IniFormat, QSettings.UserScope, 'MyOrg', ) # application='MyApp', )
|
||||
current_dir = settings.value('current_directory', DEFAULT_DIRECTORY, type=str)
|
||||
options |= QFileDialog.DontUseNativeDialog
|
||||
self.filename, _ = QtWidgets.QFileDialog.getOpenFileName(
|
||||
self,
|
||||
_translate("MainWindow_reach", "Ouvrir un fichier"),
|
||||
current_dir,
|
||||
_translate("MainWindow_reach",
|
||||
"Fichiers .ST (*.ST)") + ";;" +
|
||||
_translate("MainWindow_reach",
|
||||
"Fichiers textes (*.txt)") + ";; " +
|
||||
_translate("MainWindow_reach",
|
||||
"Tous les fichiers (*)"),
|
||||
options=options
|
||||
)
|
||||
|
||||
current_dir = os.path.split(self.filename)[0] or DEFAULT_DIRECTORY
|
||||
settings.setValue('current_directory', current_dir)
|
||||
if self.filename != "":
|
||||
size = os.stat(self.filename).st_size
|
||||
|
||||
self.bief_name = pathlib.Path(self.filename).stem
|
||||
self.setWindowTitle(f"{self.ui.mainwindow_title} {self.bief_name}")
|
||||
self.model = qtableview_reach.PandasModelEditable(self.filename, self.tableView_header)
|
||||
self.tableView.setModel(self.model)
|
||||
self.update_text_label()
|
||||
|
||||
self.update_profile_windows()
|
||||
self.graphic_1()
|
||||
self.graphic_2()
|
||||
self.graphic_3()
|
||||
self.fichier_ouvert = True
|
||||
|
||||
# Profile selection when line change in table
|
||||
self.tableView.selectionModel().selectionChanged.connect(
|
||||
self.select_current_profile
|
||||
)
|
||||
|
||||
# Update plot when profile data change
|
||||
self.model.dataChanged.connect(self.update_graphic_1)
|
||||
self.model.dataChanged.connect(self.update_graphic_2)
|
||||
self.tableView.selectionModel().selectionChanged.connect(self.update_graphic_1)
|
||||
self.tableView.selectionModel().selectionChanged.connect(self.update_graphic_2)
|
||||
|
||||
|
||||
def update_text_label(self):
|
||||
"""
|
||||
Returns: Cette méthode met à jour le texte (en haut à gauche) indiquant le nombre de profils et
|
||||
l'ordre des sections.
|
||||
"""
|
||||
if self.filename:
|
||||
if self.model.rowCount() > 1:
|
||||
self.ui.label_section_order.setText(
|
||||
f"{self.model.rowCount()}" + " " +
|
||||
_translate("MainWindow_reach", "profils") +
|
||||
f"{self.ui.text_section_order}"
|
||||
)
|
||||
else:
|
||||
self.ui.label_section_order.setText(
|
||||
f"{self.model.rowCount()}" + " " +
|
||||
_translate("MainWindow_reach", "profil") +
|
||||
f"{self.ui.text_section_order}"
|
||||
)
|
||||
|
||||
def messagebox_profile_editing(self):
|
||||
msg_box = QtWidgets.QMessageBox()
|
||||
msg_box.setIcon(QtWidgets.QMessageBox.Information)
|
||||
msg_box.setWindowTitle(_translate("MainWindow_reach",
|
||||
"Édition des profils sélectionnés"))
|
||||
msg_box.setText(_translate("MainWindow_reach",
|
||||
"Vous avez sélectionné plus de 5 profils."
|
||||
" \nSeuls les 5 premiers seront édités."))
|
||||
msg_box.setStandardButtons(QtWidgets.QMessageBox.Ok)
|
||||
|
||||
return_value = msg_box.exec()
|
||||
if return_value == QtWidgets.QMessageBox.Ok:
|
||||
print('OK clicked')
|
||||
|
||||
def edit_profile(self):
|
||||
list_selected_row = list(
|
||||
set([index.row() for index in self.tableView.selectedIndexes()])
|
||||
)
|
||||
|
||||
self.tableView.model().blockSignals(True)
|
||||
|
||||
if len(list_selected_row) > 5:
|
||||
self.messagebox_profile_editing()
|
||||
|
||||
for selected_row in list_selected_row[:5]:
|
||||
selected_row = int(selected_row)
|
||||
profile_identifier = self.model.get_profile_selected_identifier(selected_row)
|
||||
Pk = self.model.get_pk_i(selected_row)
|
||||
profile_name = self.model.get_profile_name(selected_row)
|
||||
|
||||
if len(self.list_second_window) == 0:
|
||||
self.second_window = window_profileXYZ.View(
|
||||
selected_row + 1,
|
||||
self.model.get_profile_via_identifier(profile_identifier),
|
||||
pk=Pk, profile_name="", parent=self
|
||||
)
|
||||
self.second_window.window_title(
|
||||
pk=Pk,
|
||||
profile_name=profile_name,
|
||||
profile_selected_num=selected_row
|
||||
)
|
||||
self.second_window.setWindowFlags(Qt.Window | Qt.WindowStaysOnTopHint)
|
||||
self.list_second_window.append(self.second_window)
|
||||
self.second_window.show()
|
||||
self.list_row.append(profile_identifier)
|
||||
|
||||
else:
|
||||
if profile_identifier in self.list_row:
|
||||
self.list_second_window[self.list_row.index(profile_identifier)]\
|
||||
.window_title(
|
||||
pk=Pk, profile_name=profile_name,
|
||||
profile_selected_num=selected_row
|
||||
)
|
||||
|
||||
self.list_second_window[
|
||||
self.list_row.index(profile_identifier)
|
||||
].setWindowFlags(Qt.Window | Qt.WindowStaysOnTopHint)
|
||||
|
||||
self.list_second_window[
|
||||
self.list_row.index(profile_identifier)
|
||||
].show()
|
||||
else:
|
||||
second_window1 = window_profileXYZ.View(
|
||||
selected_row + 1,
|
||||
self.model.get_profile_via_identifier(profile_identifier),
|
||||
pk=Pk, profile_name="", parent=self
|
||||
)
|
||||
second_window1.window_title(
|
||||
pk=Pk, profile_name=profile_name,
|
||||
profile_selected_num=selected_row
|
||||
)
|
||||
|
||||
second_window1.setWindowFlags(Qt.Window | Qt.WindowStaysOnTopHint)
|
||||
second_window1.show()
|
||||
self.list_row.append(profile_identifier)
|
||||
self.list_second_window.append(second_window1)
|
||||
|
||||
widgetList = QApplication.topLevelWidgets()
|
||||
numWindows = len(widgetList)
|
||||
self.tableView.model().blockSignals(False)
|
||||
|
||||
def wind_profile_changed(self):
|
||||
self.second_window\
|
||||
.datachanged_signal[bool]\
|
||||
.connect(self.changed_profile_slot)
|
||||
|
||||
pyqtSlot(bool)
|
||||
|
||||
def changed_profile_slot(self, status):
|
||||
print("status du changement ", status)
|
||||
self.update_view1 = status
|
||||
print(self.update_view1)
|
||||
|
||||
def update_graphic_1_profile(self):
|
||||
if self.update_view1:
|
||||
self.update_graphic_1()
|
||||
print("update_graphic_1_profile")
|
||||
|
||||
def print_data(self):
|
||||
print(self.model_data.profile)
|
||||
|
||||
def update_profile_windows(self):
|
||||
self.list_second_window = []
|
||||
self.list_row = []
|
||||
|
||||
def graphic_1(self):
|
||||
self.ui.canvas_1.axes.cla()
|
||||
self.ui.canvas_1.axes.grid(color='grey', linestyle='--', linewidth=0.5)
|
||||
self.ui.canvas_1.axes.set_xlabel(
|
||||
_translate("MainWindow_reach", "X (m)"), color='green', fontsize=12
|
||||
)
|
||||
self.ui.canvas_1.axes.set_ylabel(
|
||||
_translate("MainWindow_reach", "Y (m)"), color='green', fontsize=12
|
||||
)
|
||||
|
||||
self.get_x = self.model.get_x()
|
||||
self.get_y = self.model.get_y()
|
||||
self.line_xy = [
|
||||
self.ui.canvas_1.axes.plot(x, y, color='r', lw=1., markersize=3, marker='+')
|
||||
for x, y in zip(self.get_x, self.get_y)
|
||||
]
|
||||
|
||||
self.get_x_complete_list_ld = self.model.get_x_complete_list_ld()
|
||||
self.get_y_complete_list_ld = self.model.get_y_complete_list_ld()
|
||||
self.line_ld_1 = self.ui.canvas_1.axes.plot(
|
||||
self.get_x_complete_list_ld,
|
||||
self.get_y_complete_list_ld
|
||||
)
|
||||
|
||||
self.plot_selected_1, = self.ui.canvas_1.axes.plot(
|
||||
self.model.get_x_profile_i(0),
|
||||
self.model.get_y_profile_i(0), lw=1., markersize=3,
|
||||
marker='+', color="b"
|
||||
)
|
||||
|
||||
self.plot_selected_1.set_visible(False)
|
||||
self.before_plot_selected_1, = self.ui.canvas_1.axes.plot(
|
||||
self.model.get_x_profile_i(0),
|
||||
self.model.get_y_profile_i(0), lw=1., markersize=3,
|
||||
marker='+', color="k", linestyle="--"
|
||||
)
|
||||
|
||||
self.before_plot_selected_1.set_visible(False)
|
||||
|
||||
self.after_plot_selected_1, = self.ui.canvas_1.axes.plot(
|
||||
self.model.get_x_profile_i(0),
|
||||
self.model.get_y_profile_i(0), lw=1., markersize=3,
|
||||
marker='+', color="m", linestyle='--'
|
||||
)
|
||||
|
||||
self.after_plot_selected_1.set_visible(False)
|
||||
|
||||
self.ui.canvas_1.figure.tight_layout()
|
||||
self.ui.canvas_1.figure.canvas.draw_idle()
|
||||
self.ui.toolbar_1.update()
|
||||
|
||||
def graphic_2(self):
|
||||
self.tableView.model().blockSignals(True)
|
||||
|
||||
self.ui.canvas_2.axes.cla()
|
||||
self.ui.canvas_2.axes.grid(color='grey', linestyle='--', linewidth=0.5)
|
||||
self.ui.canvas_2.axes.set_xlabel(
|
||||
_translate("MainWindow_reach", "Pk (m)"), color='green', fontsize=12
|
||||
)
|
||||
self.ui.canvas_2.axes.set_ylabel(
|
||||
_translate("MainWindow_reach", "Cote (m)"), color='green', fontsize=12
|
||||
)
|
||||
|
||||
self.get_pk = self.model.get_pk()
|
||||
self.get_z_min = self.model.get_z_min()
|
||||
self.get_z_max = self.model.get_z_max()
|
||||
|
||||
self.line_pk_zmin_zmax = self.ui.canvas_2.axes.vlines(
|
||||
x=self.get_pk,
|
||||
ymin=self.get_z_min, ymax=self.get_z_max,
|
||||
color='r', lw=1.
|
||||
)
|
||||
|
||||
self.plot_selected_2, = self.ui.canvas_2.axes.plot(
|
||||
(self.get_pk[0], self.get_pk[0]),
|
||||
(self.get_z_min[0], self.get_z_max[0]),
|
||||
color='b', lw=1.8
|
||||
)
|
||||
self.plot_selected_2.set_visible(False)
|
||||
|
||||
self.before_plot_selected_2, = self.ui.canvas_2.axes.plot(
|
||||
(self.get_pk[0], self.get_pk[0]),
|
||||
(self.get_z_min[0], self.get_z_max[0]),
|
||||
color='k', lw=1.6, linestyle='--'
|
||||
)
|
||||
self.before_plot_selected_2.set_visible(False)
|
||||
|
||||
self.after_plot_selected_2, = self.ui.canvas_2.axes.plot(
|
||||
(self.get_pk[0], self.get_pk[0]),
|
||||
(self.get_z_min[0], self.get_z_max[0]),
|
||||
color='m', lw=1.6, linestyle='--'
|
||||
)
|
||||
self.after_plot_selected_2.set_visible(False)
|
||||
|
||||
try:
|
||||
self.line_pk_zld = [
|
||||
self.ui.canvas_2.axes.plot(
|
||||
self.model.get_pk(), i, lw=1.
|
||||
) for i in self.model.z_complete_guideline()
|
||||
]
|
||||
except:
|
||||
print("TODO")
|
||||
|
||||
self.line_pk_zmin, = self.ui.canvas_2.axes.plot(
|
||||
self.get_pk, self.get_z_min,
|
||||
linestyle=":", lw=1.8,
|
||||
color='lightgrey'
|
||||
)
|
||||
|
||||
self.tableView.model().blockSignals(False)
|
||||
|
||||
self.ui.canvas_2.figure.tight_layout()
|
||||
self.ui.canvas_2.figure.canvas.draw_idle()
|
||||
self.ui.toolbar_2.update()
|
||||
|
||||
def update_graphic_1(self):
|
||||
self.tableView.model().blockSignals(True)
|
||||
|
||||
for ind in range(self.model.rowCount()):
|
||||
self.line_xy[ind][0].set_data(
|
||||
self.model.get_x_profile_i(ind),
|
||||
self.model.get_y_profile_i(ind)
|
||||
)
|
||||
|
||||
for i in range(len(self.line_ld_1)):
|
||||
self.line_ld_1[i].set_data(
|
||||
[x[i] for x in self.get_x_complete_list_ld],
|
||||
[y[i] for y in self.get_y_complete_list_ld]
|
||||
)
|
||||
|
||||
self.tableView.model().blockSignals(False)
|
||||
self.ui.canvas_1.figure.canvas.draw_idle()
|
||||
|
||||
def update_graphic_2(self):
|
||||
self.tableView.model().blockSignals(True)
|
||||
|
||||
get_pk = self.model.get_pk()
|
||||
get_z_min = self.model.get_z_min()
|
||||
get_z_max = self.model.get_z_max()
|
||||
|
||||
self.line_pk_zmin.set_data(get_pk, get_z_min)
|
||||
|
||||
self.line_pk_zmin_zmax.remove()
|
||||
self.line_pk_zmin_zmax = self.ui.canvas_2.axes.vlines(
|
||||
x=get_pk,
|
||||
ymin=get_z_min, ymax=get_z_max,
|
||||
color='r', lw=1.
|
||||
)
|
||||
|
||||
try:
|
||||
for i in range(len(self.line_pk_zld)):
|
||||
self.line_pk_zld[i][0].set_data(
|
||||
get_pk, self.model.z_complete_guideline()[i]
|
||||
)
|
||||
except:
|
||||
print("TODO")
|
||||
|
||||
self.tableView.model().blockSignals(False)
|
||||
self.ui.canvas_2.axes.autoscale_view(True, True, True)
|
||||
self.ui.canvas_2.figure.canvas.draw_idle()
|
||||
|
||||
def graphic_3(self):
|
||||
self.tableView.model().blockSignals(True)
|
||||
|
||||
selected_profile = 0
|
||||
station = self.model.get_station(selected_profile) # L'abscisse en travers
|
||||
station_plus_1 = self.model.get_station(selected_profile + 1)
|
||||
elevation = self.model.get_z_profile_i(selected_profile)
|
||||
elevation_i_plus_1 = self.model.get_z_profile_i(selected_profile + 1)
|
||||
ld = self.model.get_ld_profile_i(selected_profile)
|
||||
|
||||
self.ui.canvas_3.axes.cla()
|
||||
self.ui.canvas_3.axes.grid(color='grey', linestyle='--', linewidth=0.5)
|
||||
self.ui.canvas_3.axes.set_xlabel(
|
||||
_translate("MainWindow_reach", "Abscisse en travers (m)"),
|
||||
color='green', fontsize=12
|
||||
)
|
||||
self.ui.canvas_3.axes.set_ylabel(
|
||||
_translate("MainWindow_reach", "Cote (m)"),
|
||||
color='green', fontsize=12
|
||||
)
|
||||
self.ui.canvas_3.figure.tight_layout()
|
||||
|
||||
label_profile_i_minus_1 = _translate("MainWindow_reach", "Profil précédent")
|
||||
label_profile_i = _translate("MainWindow_reach", "Profil sélectionné")
|
||||
label_profile_i_plus_1 = _translate("MainWindow_reach", "Profil suivant")
|
||||
color_profile_i_minus_1 = "k" # 'grey'
|
||||
color_profile_i = 'b'
|
||||
color_profile_i_plus_1 = 'm'
|
||||
|
||||
self.profile_i_minus_1, = self.ui.canvas_3.axes.plot(
|
||||
[], [], label=label_profile_i_minus_1, lw=1.8,
|
||||
linestyle='--', color=color_profile_i_minus_1
|
||||
)
|
||||
self.profile_i, = self.ui.canvas_3.axes.plot(
|
||||
station, elevation, label=label_profile_i,
|
||||
color=color_profile_i, lw=1.8
|
||||
)
|
||||
|
||||
self.profile_i_plus_1, = self.ui.canvas_3.axes.plot(
|
||||
station_plus_1, elevation_i_plus_1,
|
||||
label=label_profile_i_plus_1,
|
||||
color=color_profile_i_plus_1, lw=1.6, linestyle='--'
|
||||
)
|
||||
self.annotation_3 = []
|
||||
self.complete_list_ld = self.model.get_complete_list_ld()
|
||||
self.incomplete_list_ld = self.model.get_incomplete_list_ld()
|
||||
|
||||
line_2d = [[line_2D] for line_2D in self.line_ld_1]
|
||||
self.color_complete_ld = self.get_line_ld_colors(line_2d)
|
||||
self.color_incomplete_ld = 2 * ["#000000"]
|
||||
|
||||
x_ld_complete = []
|
||||
y_ld_complete = []
|
||||
color_scat_complete_ld = []
|
||||
x_ld_incomplete = []
|
||||
y_ld_incomplete = []
|
||||
color_scat_incomplete_ld = []
|
||||
|
||||
for i, txt in enumerate(list(ld)):
|
||||
if txt.strip() in self.complete_list_ld:
|
||||
annotation_3 = self.ui.canvas_3.axes.annotate(
|
||||
txt, (station[i], elevation[i]),
|
||||
horizontalalignment='left',
|
||||
verticalalignment='top', annotation_clip=True,
|
||||
fontsize=10,
|
||||
color=self.color_complete_ld[
|
||||
self.complete_list_ld.index(txt)
|
||||
]
|
||||
)
|
||||
|
||||
annotation_3.set_position((station[i] + 0., elevation[i] + 0.))
|
||||
self.annotation_3.append(annotation_3)
|
||||
|
||||
x_ld_complete.append(station[i])
|
||||
y_ld_complete.append(elevation[i])
|
||||
color_scat_complete_ld.append(self.color_complete_ld[self.complete_list_ld.index(txt)])
|
||||
elif txt.strip() in self.incomplete_list_ld:
|
||||
annotate = self.ui.canvas_3.axes.annotate(
|
||||
txt, (station[i], elevation[i]), horizontalalignment='left',
|
||||
verticalalignment='top', annotation_clip=True, fontsize=11,
|
||||
color=self.color_incomplete_ld[
|
||||
self.incomplete_list_ld.index(txt)
|
||||
],
|
||||
size=10
|
||||
)
|
||||
|
||||
self.annotation_3.append(annotate)
|
||||
|
||||
x_ld_incomplete.append(station[i])
|
||||
y_ld_incomplete.append(elevation[i])
|
||||
color_scat_incomplete_ld.append(
|
||||
self.color_incomplete_ld[self.incomplete_list_ld.index(txt)]
|
||||
)
|
||||
|
||||
self.tableView.model().blockSignals(False)
|
||||
|
||||
self.ui.canvas_3.axes.legend(fancybox=True, shadow=True, fontsize=8)
|
||||
self.ui.canvas_3.figure.tight_layout()
|
||||
|
||||
self.ui.canvas_3.figure.canvas.draw_idle()
|
||||
self.ui.toolbar_3.update()
|
||||
|
||||
def update_annotate_3(self, ind: int):
|
||||
self.tableView.model().blockSignals(True)
|
||||
|
||||
for a in self.annotation_3:
|
||||
a.remove()
|
||||
|
||||
self.annotation_3[:] = []
|
||||
|
||||
x = self.get_station(ind)
|
||||
y = self.get_elevation(ind)
|
||||
ld = self.model.get_ld_profile_i(ind)
|
||||
get_complete_list_ld = self.model.get_complete_list_ld()
|
||||
get_incomplete_list_ld = self.model.get_incomplete_list_ld()
|
||||
|
||||
try:
|
||||
x_ld_complete = []
|
||||
color_scat_complete_ld = []
|
||||
x_ld_incomplete = []
|
||||
color_scat_incomplete_ld = []
|
||||
for i, txt in enumerate(list(ld)):
|
||||
if txt in get_complete_list_ld:
|
||||
annotate = self.ui.canvas_3.axes.annotate(
|
||||
txt, (x[i], y[i]), horizontalalignment='left',
|
||||
verticalalignment='top', annotation_clip=True,
|
||||
fontsize=11,
|
||||
color=self.color_complete_ld[
|
||||
get_complete_list_ld.index(txt)
|
||||
],
|
||||
size=10
|
||||
)
|
||||
self.annotation_3.append(annotate)
|
||||
x_ld_complete.append([x[i], y[i]])
|
||||
color_scat_complete_ld.append(
|
||||
self.color_complete_ld[self.complete_list_ld.index(txt)]
|
||||
)
|
||||
elif txt in get_incomplete_list_ld:
|
||||
annotate = self.ui.canvas_3.axes.annotate(
|
||||
txt, (x[i], y[i]), horizontalalignment='left',
|
||||
verticalalignment='top', annotation_clip=True,
|
||||
fontsize=11,
|
||||
color=self.color_incomplete_ld[
|
||||
get_incomplete_list_ld.index(txt)
|
||||
],
|
||||
size=10
|
||||
)
|
||||
self.annotation_3.append(annotate)
|
||||
x_ld_incomplete.append([x[i], y[i]])
|
||||
color_scat_incomplete_ld.append(
|
||||
self.color_incomplete_ld[get_incomplete_list_ld.index(txt)]
|
||||
)
|
||||
except:
|
||||
print("FIXME")
|
||||
|
||||
self.tableView.model().blockSignals(False)
|
||||
self.ui.canvas_3.figure.canvas.draw_idle()
|
||||
|
||||
def get_line_ld_colors(self, line_2d):
|
||||
colors = []
|
||||
|
||||
for line in line_2d:
|
||||
colors.append(line[0].get_color())
|
||||
|
||||
return colors
|
||||
|
||||
def get_station(self, ind: int):
|
||||
return self.model.get_station(ind)
|
||||
|
||||
def get_elevation(self, ind: int):
|
||||
return self.model.get_z_profile_i(ind)
|
||||
|
||||
def update_graphic_3(self, ind: int):
|
||||
self.tableView.model().blockSignals(True)
|
||||
|
||||
selected_profile = ind
|
||||
print(selected_profile)
|
||||
|
||||
if selected_profile == 0:
|
||||
self.profile_i_minus_1.set_data([], [])
|
||||
self.profile_i.set_data(
|
||||
self.get_station(selected_profile),
|
||||
self.get_elevation(selected_profile)
|
||||
)
|
||||
self.profile_i_plus_1.set_data(
|
||||
self.get_station(selected_profile + 1),
|
||||
self.get_elevation(selected_profile + 1)
|
||||
)
|
||||
elif selected_profile == self.model.rowCount() - 1:
|
||||
self.profile_i_minus_1.set_data(
|
||||
self.get_station(selected_profile - 1),
|
||||
self.get_elevation(selected_profile - 1)
|
||||
)
|
||||
self.profile_i.set_data(
|
||||
self.get_station(selected_profile),
|
||||
self.get_elevation(selected_profile)
|
||||
)
|
||||
self.profile_i_plus_1.set_data([], [])
|
||||
elif 0 < selected_profile < self.model.rowCount() - 1:
|
||||
self.profile_i_minus_1.set_data(
|
||||
self.get_station(selected_profile - 1),
|
||||
self.get_elevation(selected_profile - 1)
|
||||
)
|
||||
self.profile_i.set_data(
|
||||
self.get_station(selected_profile),
|
||||
self.get_elevation(selected_profile)
|
||||
)
|
||||
self.profile_i_plus_1.set_data(
|
||||
self.get_station(selected_profile + 1),
|
||||
self.get_elevation(selected_profile + 1)
|
||||
)
|
||||
|
||||
self.tableView.model().blockSignals(False)
|
||||
|
||||
self.update_annotate_3(selected_profile)
|
||||
|
||||
self.ui.canvas_3.axes.relim()
|
||||
self.ui.canvas_3.axes.autoscale_view()
|
||||
self.ui.canvas_3.figure.canvas.draw_idle()
|
||||
|
||||
def select_plot_graphic_1(self, ind: int):
|
||||
self.tableView.model().blockSignals(True)
|
||||
|
||||
if 0 <= ind < self.model.rowCount():
|
||||
self.plot_selected_1.set_data(self.model.get_x_profile_i(ind),
|
||||
self.model.get_y_profile_i(ind))
|
||||
self.plot_selected_1.set_visible(True)
|
||||
self.tableView.model().blockSignals(False)
|
||||
|
||||
def select_plot_graphic_2(self, ind: int):
|
||||
get_pk_i = self.get_pk_i(ind)
|
||||
get_z_min_i = self.get_z_min_i(ind)
|
||||
get_z_max_i = self.get_z_max_i(ind)
|
||||
|
||||
if 0 <= ind < self.model.rowCount():
|
||||
self.plot_selected_2.set_data((get_pk_i, get_pk_i),
|
||||
(get_z_min_i, get_z_max_i))
|
||||
self.plot_selected_2.set_visible(True)
|
||||
|
||||
def select_before_plot_selected_1(self, ind: int):
|
||||
if 0 <= ind < self.model.rowCount():
|
||||
t0 = time.time()
|
||||
|
||||
self.before_plot_selected_1.set_data(
|
||||
self.model.get_x_profile_i(ind),
|
||||
self.model.get_y_profile_i(ind)
|
||||
)
|
||||
|
||||
self.before_plot_selected_1.set_visible(True)
|
||||
self.ui.canvas_1.figure.canvas.draw_idle()
|
||||
|
||||
def select_after_plot_selected_1(self, ind: int):
|
||||
if 0 <= ind < self.model.rowCount():
|
||||
self.after_plot_selected_1.set_data(
|
||||
self.model.get_x_profile_i(ind),
|
||||
self.model.get_y_profile_i(ind)
|
||||
)
|
||||
self.after_plot_selected_1.set_visible(True)
|
||||
self.ui.canvas_1.figure.canvas.draw_idle()
|
||||
|
||||
def select_before_plot_selected_2(self, ind: int):
|
||||
if 0 <= ind < self.model.rowCount():
|
||||
t0 = time.time()
|
||||
get_pk_i = self.get_pk_i(ind)
|
||||
get_z_min_i = self.get_z_min_i(ind)
|
||||
get_z_max_i = self.get_z_max_i(ind)
|
||||
|
||||
self.before_plot_selected_2.set_data(
|
||||
(get_pk_i, get_pk_i),
|
||||
(get_z_min_i, get_z_max_i)
|
||||
)
|
||||
|
||||
self.before_plot_selected_2.set_visible(True)
|
||||
self.ui.canvas_2.figure.canvas.draw_idle()
|
||||
|
||||
def select_after_plot_selected_2(self, ind: int):
|
||||
if 0 <= ind < self.model.rowCount():
|
||||
t0 = time.time()
|
||||
get_pk_i = self.get_pk_i(ind)
|
||||
get_z_min_i = self.get_z_min_i(ind)
|
||||
get_z_max_i = self.get_z_max_i(ind)
|
||||
self.after_plot_selected_2.set_data(
|
||||
(get_pk_i, get_pk_i),
|
||||
(get_z_min_i, get_z_max_i)
|
||||
)
|
||||
self.after_plot_selected_2.set_visible(True)
|
||||
self.ui.canvas_2.figure.canvas.draw_idle()
|
||||
|
||||
def select_row_profile_slider(self, ind: int = 0):
|
||||
if self.tableView is not None:
|
||||
selectionModel = self.tableView.selectionModel()
|
||||
index = self.tableView.model().index(ind, 0)
|
||||
|
||||
selectionModel.select(
|
||||
index,
|
||||
QItemSelectionModel.Rows |
|
||||
QItemSelectionModel.ClearAndSelect |
|
||||
QItemSelectionModel.Select
|
||||
)
|
||||
|
||||
self.tableView.scrollTo(index)
|
||||
|
||||
def select_current_profile(self):
|
||||
self.tableView.model().blockSignals(True)
|
||||
|
||||
if len(self.tableView.selectedIndexes()) > 0:
|
||||
row = self.index_selected_row
|
||||
|
||||
self.ui.verticalSlider.setValue(row)
|
||||
self.select_plot_graphic_1(row)
|
||||
self.select_plot_graphic_2(row)
|
||||
|
||||
if row == 0:
|
||||
self.before_plot_selected_1.set_visible(False)
|
||||
self.select_after_plot_selected_1(row + 1)
|
||||
self.before_plot_selected_2.set_visible(False)
|
||||
self.select_after_plot_selected_2(row + 1)
|
||||
elif 0 < row < self.model.rowCount() - 1:
|
||||
self.select_before_plot_selected_1(row - 1)
|
||||
self.select_after_plot_selected_1(row + 1)
|
||||
self.select_before_plot_selected_2(row - 1)
|
||||
self.select_after_plot_selected_2(row + 1)
|
||||
elif row == self.model.rowCount() - 1:
|
||||
self.after_plot_selected_1.set_visible(False)
|
||||
self.select_before_plot_selected_1(row - 1)
|
||||
self.after_plot_selected_2.set_visible(False)
|
||||
self.select_before_plot_selected_2(row - 1)
|
||||
self.tableView.model().blockSignals(False)
|
||||
|
||||
self.update_graphic_3(row)
|
||||
|
||||
self.ui.canvas_1.figure.canvas.draw_idle()
|
||||
self.ui.canvas_2.figure.canvas.draw_idle()
|
||||
|
||||
def changed_slider_value(self):
|
||||
self.tableView.model().blockSignals(True)
|
||||
|
||||
if self.filename is not None:
|
||||
self.ui.verticalSlider.setMaximum(self.model.rowCount() - 1)
|
||||
|
||||
slider_value = self.ui.verticalSlider.value()
|
||||
|
||||
pk = self.model.get_pk_profile_i(slider_value)
|
||||
self.ui.vertical_slider_label.setText(
|
||||
_translate("MainWindow_reach", "Pk : ") +
|
||||
f"{pk}" + "\n" +
|
||||
_translate("MainWindow_reach",
|
||||
"Profil N° : ") +
|
||||
f"{slider_value + 1}"
|
||||
)
|
||||
|
||||
self.select_plot_graphic_1(slider_value)
|
||||
self.select_plot_graphic_2(slider_value)
|
||||
self.select_row_profile_slider(slider_value)
|
||||
|
||||
self.tableView.model().blockSignals(False)
|
||||
|
||||
def increment_value_slider(self):
|
||||
if 0 <= self.ui.verticalSlider.value() < self.model.rowCount() - 1:
|
||||
self.ui.verticalSlider.setValue(self.ui.verticalSlider.value() + 1)
|
||||
|
||||
def decrement_value_slider(self):
|
||||
if 0 < self.ui.verticalSlider.value() < self.model.rowCount():
|
||||
self.ui.verticalSlider.setValue(self.ui.verticalSlider.value() - 1)
|
||||
|
||||
def insert_row(self):
|
||||
if len(self.tableView.selectedIndexes()) == 0:
|
||||
self.model.insertRows(self.model.rowCount(), 1)
|
||||
else:
|
||||
row = self.index_selected_row
|
||||
self.model.insertRows(row + 1, 1)
|
||||
|
||||
if self.filename is not None:
|
||||
self.graphic_1()
|
||||
self.graphic_2()
|
||||
self.select_current_profile()
|
||||
|
||||
def delete_row(self):
|
||||
rows = list(set(
|
||||
[index.row() for index in self.tableView.selectedIndexes()]
|
||||
))
|
||||
|
||||
if len(rows) > 0:
|
||||
self.model.remove_rows(rows)
|
||||
|
||||
self.update_graphic_1()
|
||||
self.select_current_profile()
|
||||
|
||||
self.graphic_2()
|
||||
self.changed_slider_value()
|
||||
|
||||
@property
|
||||
def index_selected_row(self):
|
||||
return [index.row() for index in self.tableView.selectedIndexes()][0]
|
||||
|
||||
def sort_ascending(self):
|
||||
self.model.sort_data(True)
|
||||
self.select_current_profile()
|
||||
self.changed_slider_value()
|
||||
|
||||
self.update_graphic_2()
|
||||
self.update_graphic_3(self.index_selected_row)
|
||||
|
||||
def sort_descending(self):
|
||||
self.model.sort_data(False)
|
||||
|
||||
self.select_current_profile()
|
||||
self.changed_slider_value()
|
||||
|
||||
self.update_graphic_2()
|
||||
self.update_graphic_3(self.index_selected_row)
|
||||
|
||||
def move_row_down(self):
|
||||
row = self.index_selected_row
|
||||
|
||||
if row < self.model.rowCount() - 1:
|
||||
self.model.moveRowDown(row)
|
||||
self.update_graphic_3(row + 1)
|
||||
self.ui.canvas_3.axes.relim()
|
||||
self.ui.canvas_3.axes.autoscale_view()
|
||||
|
||||
if row < self.model.rowCount() - 2:
|
||||
self.select_before_plot_selected_1(row)
|
||||
self.select_after_plot_selected_1(row + 2)
|
||||
self.select_before_plot_selected_2(row)
|
||||
self.select_after_plot_selected_2(row + 2)
|
||||
|
||||
if row == self.model.rowCount() - 2:
|
||||
self.select_before_plot_selected_1(self.model.rowCount() - 2)
|
||||
self.after_plot_selected_1.set_visible(False)
|
||||
self.select_before_plot_selected_2(self.model.rowCount() - 2)
|
||||
self.after_plot_selected_2.set_visible(False)
|
||||
|
||||
self.update_graphic_2()
|
||||
|
||||
def move_row_up(self):
|
||||
row = self.index_selected_row
|
||||
|
||||
if 0 < row <= self.model.rowCount() - 1:
|
||||
self.model.moveRowUp(row)
|
||||
|
||||
if row == 1:
|
||||
self.select_after_plot_selected_1(row)
|
||||
self.before_plot_selected_1.set_visible(False)
|
||||
self.select_after_plot_selected_2(row)
|
||||
self.before_plot_selected_2.set_visible(False)
|
||||
|
||||
elif row == self.model.rowCount() - 1:
|
||||
self.select_before_plot_selected_1(row - 2)
|
||||
self.select_after_plot_selected_1(row)
|
||||
self.select_before_plot_selected_2(row - 2)
|
||||
self.select_after_plot_selected_2(row)
|
||||
|
||||
else:
|
||||
self.select_before_plot_selected_1(row - 2)
|
||||
self.select_after_plot_selected_1(row)
|
||||
self.select_before_plot_selected_2(row - 2)
|
||||
self.select_after_plot_selected_2(row)
|
||||
|
||||
self.update_graphic_2()
|
||||
self.update_graphic_3(row - 1)
|
||||
self.ui.canvas_3.axes.relim()
|
||||
self.ui.canvas_3.axes.autoscale_view()
|
||||
|
||||
def handleSave(self):
|
||||
options = QFileDialog.Options()
|
||||
DEFAULT_DIRECTORY = '/home/'
|
||||
settings = QSettings(QSettings.IniFormat, QSettings.UserScope, 'MyOrg', )
|
||||
current_dir = settings.value('current_directory', DEFAULT_DIRECTORY, type=str)
|
||||
options |= QFileDialog.DontUseNativeDialog
|
||||
|
||||
filename, self.filters = QFileDialog.getSaveFileName(
|
||||
self,
|
||||
filter=_translate("MainWindow_reach",
|
||||
"Fichiers .ST(*.ST ou *.st)")
|
||||
+ ";; " +
|
||||
_translate("MainWindow_reach", "Tous les fichiers "
|
||||
"(*)"),
|
||||
options=options
|
||||
)
|
||||
|
||||
current_dir = os.path.split(filename)[0] or DEFAULT_DIRECTORY
|
||||
|
||||
if filename != '':
|
||||
self.model.export_reach(filename)
|
||||
|
||||
def handleOpen(self):
|
||||
self.filename, self.filterName = QFileDialog.getOpenFileName(self)
|
||||
|
||||
if self.filename != '':
|
||||
with open(self.filename, 'r') as f:
|
||||
reader = csv.reader(f, delimiter='\t')
|
||||
header = next(reader)
|
||||
buf = []
|
||||
for row in reader:
|
||||
row[0] = QCheckBox("-")
|
||||
buf.append(row)
|
||||
|
||||
self.model = None
|
||||
self.model = qtableview_reach.PandasModelEditable(buf)
|
||||
self.tableView.setModel(self.model)
|
||||
self.filename = ''
|
||||
|
||||
def get_lignes_directrices(self):
|
||||
liste_lignes_directrices = [
|
||||
data[1].iloc[:, 3].tolist() for data in self.model._data
|
||||
]
|
||||
return liste_lignes_directrices
|
||||
|
||||
def get_x(self):
|
||||
return self.model.get_x()
|
||||
|
||||
def get_y(self):
|
||||
return self.model.get_y()
|
||||
|
||||
def get_z(self):
|
||||
return self.model.get_z()
|
||||
|
||||
def get_z_min(self):
|
||||
return self.model.get_z_min()
|
||||
|
||||
def get_z_min_i(self, index):
|
||||
return self.model.get_z_min_i(index)
|
||||
|
||||
def get_z_max_i(self, index):
|
||||
return self.model.get_z_max_i(index)
|
||||
|
||||
def get_z_max(self):
|
||||
return self.model.get_z_max()
|
||||
|
||||
def get_pk(self):
|
||||
return self.model.get_pk()
|
||||
|
||||
def get_pk_i(self, index):
|
||||
return self.model.get_pk_i(index)
|
||||
|
||||
def get_pk_z_ld(self):
|
||||
return self.model.get_pk_z_ld()
|
||||
|
||||
def get_pk_z_ld_bis(self):
|
||||
return self.model.get_pk_z_ld_bis()
|
||||
|
||||
@property
|
||||
def model_data(self):
|
||||
return self.model.model_data()
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg
|
||||
from matplotlib.figure import Figure
|
||||
|
||||
|
||||
class MplCanvas(FigureCanvasQTAgg):
|
||||
|
||||
def __init__(self, width=5, height=4, dpi=100):
|
||||
fig = Figure(figsize=(width, height), dpi=dpi)
|
||||
super(MplCanvas, self).__init__(fig)
|
||||
|
||||
self.axes = fig.add_subplot(111)
|
||||
self.axes.format_coord = lambda x, y: '(x = ' + format(x, '1.4f') + ', \t' + ' y = ' + format(y, '1.4f') + ')'
|
||||
self.axes.grid(color='green', linestyle='--', linewidth=0.5)
|
||||
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):
|
||||
al = 8.
|
||||
arrowprops = dict(
|
||||
clip_on=True,
|
||||
# frac=1.,
|
||||
headwidth=5.,
|
||||
facecolor='k'
|
||||
)
|
||||
kwargs = dict(
|
||||
xycoords='axes fraction',
|
||||
textcoords='offset points',
|
||||
arrowprops=arrowprops,
|
||||
)
|
||||
self.axes.annotate("", (1, 0), xytext=(-al, 0), **kwargs)
|
||||
self.axes.annotate("", (0, 1), xytext=(0, -al), **kwargs)
|
||||
|
|
@ -0,0 +1,488 @@
|
|||
from time import time
|
||||
|
||||
import numpy as np
|
||||
from PyQt5 import QtWidgets
|
||||
from PyQt5.QtCore import QItemSelectionModel, Qt
|
||||
from PyQt5.QtWidgets import QApplication
|
||||
from shapely.geometry.polygon import Polygon as ShapelyPolygon
|
||||
|
||||
|
||||
class OnpickEvent(object):
|
||||
def __init__(self, ax, x, y, x_carto, y_carto, tableview=None):
|
||||
"""
|
||||
Args:
|
||||
ax: objet Axes.
|
||||
x: abscisse x1 du graphe (f(x1) = y1) à tracer.
|
||||
y: ordonnée y1 du graphe (f(x1) = y1) à tracer.
|
||||
x_carto: (vecteur) abscisse des points (X,Y,Z) du profil.
|
||||
y_carto: (vecteur) abscisse des points (X,Y,Z) du profil
|
||||
tableview: tableau (de type QtableView) 'associé' au grahique.
|
||||
"""
|
||||
self.ax = ax
|
||||
self.x = x
|
||||
self.y = y
|
||||
self.x_carto = x_carto
|
||||
self.y_carto = y_carto
|
||||
self.tableView = tableview
|
||||
self.counter_onclick = 0
|
||||
# self.select_point_plot()
|
||||
self.count = 0
|
||||
self.annotation_onclick = self.ax.annotate("", xytext=(np.mean(self.x), np.mean(self.y)),
|
||||
xy=(np.mean(self.x), np.mean(self.y)),
|
||||
horizontalalignment='center',
|
||||
fontsize=8,
|
||||
# fontstyle='italic',
|
||||
fontweight='bold',
|
||||
alpha=0.7
|
||||
|
||||
)
|
||||
self.annotation_onclick.set_visible(False)
|
||||
self.pos_x = 0
|
||||
self.zomm_xmin_xmax = self.ax.get_xlim()
|
||||
self.plot_selec()
|
||||
# self.select_point_plot()
|
||||
self._largeur_miroir, = self.ax.plot(self.x[1], self.y[1],
|
||||
color='blue', lw=1.2, ls=":")
|
||||
|
||||
self.pt = []
|
||||
self.tableView.selectionModel().selectionChanged.connect(self.update_select_point_point)
|
||||
|
||||
def select_row_pt_clicked(self, ind: int = 0):
|
||||
"""
|
||||
Args:
|
||||
ind: Indice de la ligne où se trouve le point le plus proche 'visé'.
|
||||
Returns: Sélectionne la ligne (du tableau) correspondant au point le plus proche 'visé' à la suite de l'événement onpick.
|
||||
"""
|
||||
if self.tableView is not None:
|
||||
selectionModel = self.tableView.selectionModel()
|
||||
index = self.tableView.model().index(ind, 0)
|
||||
selectionModel.select(index,
|
||||
QItemSelectionModel.Rows | QItemSelectionModel.ClearAndSelect |
|
||||
QItemSelectionModel.Select)
|
||||
self.tableView.scrollTo(index)
|
||||
|
||||
def select_qtableview_row(self, event):
|
||||
if self.tableView is not None:
|
||||
self.tableView.setFocus()
|
||||
ind = self.indice_points_onpick(event)
|
||||
dataidx_ecran = self.index_pt_plus_proche_ecran(event)
|
||||
self.select_row_pt_clicked(ind[dataidx_ecran])
|
||||
|
||||
def select_point_plot(self):
|
||||
"""
|
||||
Returns: sélectionne le(s) point(s) du graphique correspondant à la/aux ligne(s) sélectionnée(s) dans le tableau.
|
||||
"""
|
||||
if self.tableView is not None:
|
||||
rows = list(set([index.row() for index in self.tableView.selectedIndexes()]))
|
||||
for row in rows:
|
||||
pass
|
||||
|
||||
def update_select_point_point(self):
|
||||
if self.tableView is not None:
|
||||
rows = list(set([index.row() for index in self.tableView.selectedIndexes()]))
|
||||
if len(rows) > 1:
|
||||
for row in rows:
|
||||
self.pt1 = self.ax.plot(self.x[row], self.y[row], '+', c='Blue', markersize=7)
|
||||
self.pt.append(self.pt1)
|
||||
self.update_select_point_point_bis(self.x[row], self.y[row])
|
||||
|
||||
elif len(rows) == 1:
|
||||
for row in rows:
|
||||
try:
|
||||
[pl[0].set_data([], []) for pl in self.pt if len(self.pt) > 1]
|
||||
except:
|
||||
print("Probleme de mise à jour ... update_select_point_point()")
|
||||
|
||||
try:
|
||||
self.update_select_point_point_bis(self.x[row], self.y[row])
|
||||
except:
|
||||
print("index introuvable pour la mise à jour de l'affichage de la sélection du point."
|
||||
"Editer les cases en 'nan'.")
|
||||
|
||||
self.ax.figure.canvas.draw_idle()
|
||||
|
||||
def plot_selec(self):
|
||||
self.point_selec, = self.ax.plot(self.x[0], self.y[0], '+', c='Blue', markersize=7)
|
||||
self.point_selec.set_visible(False)
|
||||
|
||||
def update_select_point_point_bis(self, x_ind, y_ind):
|
||||
self.point_selec.set_data(x_ind, y_ind)
|
||||
self.point_selec.set_visible(True)
|
||||
self.ax.figure.canvas.draw_idle()
|
||||
|
||||
def plot_selection_point(self, x, y):
|
||||
"""
|
||||
Args:
|
||||
x: abscisse
|
||||
y: ordonnée
|
||||
Returns: sélectionne le point du graphique correspond à la ligne sélectionnée dans le tableau.
|
||||
"""
|
||||
if self.tableView is not None:
|
||||
self.select_point, = self.ax.plot(x, y, '+', c='Blue', markersize=7)
|
||||
else:
|
||||
self.select_point, = self.ax.plot([], [])
|
||||
|
||||
def geometrie_sans_rebord(self):
|
||||
rebord = True
|
||||
z_sans_rebord = [i for i in self.y]
|
||||
x_sans_rebord = [i for i in self.x]
|
||||
|
||||
while rebord:
|
||||
if z_sans_rebord[1] >= z_sans_rebord[0]:
|
||||
z_sans_rebord.pop(0)
|
||||
x_sans_rebord.pop(0)
|
||||
else:
|
||||
rebord = False
|
||||
|
||||
rebord = True
|
||||
while rebord:
|
||||
if z_sans_rebord[-1] <= z_sans_rebord[-2]:
|
||||
z_sans_rebord.pop()
|
||||
x_sans_rebord.pop()
|
||||
else:
|
||||
rebord = False
|
||||
|
||||
z_berge_basse = min(z_sans_rebord[0], z_sans_rebord[-1])
|
||||
|
||||
return z_berge_basse, z_sans_rebord, x_sans_rebord
|
||||
|
||||
@property
|
||||
def z_berge_basse(self):
|
||||
return self.geometrie_sans_rebord()[0]
|
||||
|
||||
@property
|
||||
def z_sans_rebord(self):
|
||||
return self.geometrie_sans_rebord()[1]
|
||||
|
||||
@property
|
||||
def x_sans_rebord(self):
|
||||
return self.geometrie_sans_rebord()[2]
|
||||
|
||||
@property
|
||||
def z_fond(self):
|
||||
return np.array(self.z_sans_rebord)
|
||||
|
||||
@property
|
||||
def z_point_bas(self):
|
||||
"""
|
||||
Returns: la cote (Zmin) du point le plus bas.
|
||||
"""
|
||||
return min(self.y)
|
||||
|
||||
@property
|
||||
def delta_x(self):
|
||||
""""
|
||||
Returns: la longueur entre les limites de la vue sur l'axe des x, c'est-à-dire |x_max_visible - x_min_visible|.
|
||||
"""
|
||||
xgauche, xdroite = self.ax.get_xlim()
|
||||
delta_x = abs(xdroite - xgauche)
|
||||
return delta_x
|
||||
|
||||
@property
|
||||
def delta_y(self):
|
||||
"""
|
||||
Returns: la longueur entre les limites de la vue sur l'axe des y, c'est à dire |y_max_visible - y_min_visible|.
|
||||
"""
|
||||
ybas, yhaut = self.ax.get_ylim()
|
||||
delta_y = abs(yhaut - ybas)
|
||||
return delta_y
|
||||
|
||||
@staticmethod
|
||||
def indice_points_onpick(event):
|
||||
"""
|
||||
Args: event
|
||||
Returns: le(s) indexe(s) du/des point(s) (plus précisement les coordonnées de points) capturé(s)
|
||||
par l'événement onpick (voir picker)
|
||||
"""
|
||||
return event.ind
|
||||
|
||||
def points_onpick(self, event):
|
||||
"""
|
||||
Args:
|
||||
event:
|
||||
Returns: une array contenant les coordonées des points qui se trouvent dans la zone définie par l'événement
|
||||
onpick (voir picker)
|
||||
|
||||
"""
|
||||
thisline = event.artist
|
||||
xdata = thisline.get_xdata()
|
||||
ydata = thisline.get_ydata()
|
||||
points_onpick = np.array([(xdata[i], ydata[i]) for i in self.indice_points_onpick(event)])
|
||||
return points_onpick
|
||||
|
||||
def distance_normee(self, event):
|
||||
"""
|
||||
Args:
|
||||
event:
|
||||
Returns: la liste des distances normées (en m) entre les points situés dans la région définie par l'événement
|
||||
onpick (voir picker).
|
||||
"""
|
||||
ind = event.ind
|
||||
thisline = event.artist
|
||||
xdata = thisline.get_xdata()
|
||||
ydata = thisline.get_ydata()
|
||||
points_onpick = np.array([(xdata[i], ydata[i]) for i in ind])
|
||||
distances_normees = [
|
||||
(((x - event.mouseevent.xdata) / self.delta_x) ** 2 +
|
||||
((y - event.mouseevent.ydata) / self.delta_y) ** 2) ** (1 / 2)
|
||||
for (x, y) in points_onpick
|
||||
]
|
||||
return distances_normees
|
||||
|
||||
def position_souris(self, event):
|
||||
"""
|
||||
Args:
|
||||
event:
|
||||
Returns: la position de la souris
|
||||
"""
|
||||
self.pos_souris = [(event.mouseevent.xdata, event.mouseevent.ydata)]
|
||||
return self.pos_souris
|
||||
|
||||
def distance_ecran(self, event):
|
||||
"""
|
||||
Args:
|
||||
event:
|
||||
Returns: la liste des distances 'visuelles' entre les points situés dans la région définie par l'événement
|
||||
onpick (voir picker).
|
||||
"""
|
||||
bbox = self.ax.get_window_extent()\
|
||||
.transformed(self.ax.figure.dpi_scale_trans.inverted())
|
||||
ratio_w_sur_h = bbox.width / bbox.height
|
||||
distances_ecran = [
|
||||
(((x - event.mouseevent.xdata) / (self.delta_x * ratio_w_sur_h)) ** 2 +
|
||||
((y - event.mouseevent.ydata) / self.delta_y) ** 2) ** (1 / 2)
|
||||
for (x, y) in self.points_onpick(event)
|
||||
]
|
||||
|
||||
return distances_ecran
|
||||
|
||||
def distances(self, event):
|
||||
"""
|
||||
Args: event:
|
||||
Returns: la liste des distances entre la position de la souris et tous les points se trouvant dans
|
||||
la zone définie par l'événement onpick ( voir picker)
|
||||
"""
|
||||
distances = np.linalg.norm(
|
||||
self.points_onpick(event) - self.position_souris(event),
|
||||
axis=1
|
||||
)
|
||||
|
||||
return distances
|
||||
|
||||
def index_pt_plus_proche_ecran(self, event):
|
||||
"""
|
||||
Args:
|
||||
event:
|
||||
Returns: indice du point le plus proche visuellement de la position du click.
|
||||
"""
|
||||
dataidx_ecran = np.argmin(self.distance_ecran(event))
|
||||
return dataidx_ecran
|
||||
|
||||
def point_plus_proche_ecran(self, event):
|
||||
point_onpick = self.points_onpick(event)
|
||||
datapos_ecran = point_onpick[self.index_pt_plus_proche_ecran(event)]
|
||||
|
||||
return self.points_onpick(event)[self.index_pt_plus_proche_ecran(event)]
|
||||
|
||||
def index_pt_plus_proche(self, event):
|
||||
"""
|
||||
Args:
|
||||
event:
|
||||
Returns: indice du point le plus proche de la position du click.
|
||||
"""
|
||||
dataidx = np.argmin(self.distances(event))
|
||||
|
||||
return dataidx
|
||||
|
||||
def point_plus_proche(self, event):
|
||||
"""
|
||||
Args:
|
||||
event:
|
||||
Returns: point le plus proche de la position du click
|
||||
"""
|
||||
point_onpick = self.points_onpick(event)
|
||||
datapos = point_onpick[self.index_pt_plus_proche(event)]
|
||||
|
||||
return datapos
|
||||
|
||||
def annotate_onpick(self, x, y):
|
||||
"""
|
||||
Args:
|
||||
x: abscisse du point à annoter.
|
||||
y: ordonnée du point à annoter.
|
||||
Returns: annote le point xy avec du texte text = xytext.
|
||||
"""
|
||||
return self.ax.annotate(
|
||||
"X", xytext=(x, y),
|
||||
xy=(x, y), fontsize=9,
|
||||
bbox=dict(
|
||||
boxstyle='round,pad=0.8', fc='yellow', alpha=0.75
|
||||
),
|
||||
arrowprops=dict(
|
||||
arrowstyle='->',
|
||||
connectionstyle='arc3,rad=0.',
|
||||
color='blue'
|
||||
)
|
||||
)
|
||||
|
||||
def on_ylims_change(self, event_ax):
|
||||
return event_ax.get_ylim()
|
||||
|
||||
def annotate_onclick(self, event):
|
||||
if self.z_point_bas <= event.ydata:
|
||||
self.count += 1
|
||||
|
||||
if event.ydata <= self.z_berge_basse:
|
||||
A, p, L = self.calcul_ligne_eau(event.ydata)
|
||||
else:
|
||||
event.ydata = self.z_berge_basse
|
||||
A, p, L = self.calcul_ligne_eau(event.ydata)
|
||||
|
||||
etiq = f"Z = {event.ydata:.3f} m, A = {A:.3f} m\u00B2, p = {p:.3f} m, L = {L:.3f} m"
|
||||
self.annotation_onclick.set_text(etiq)
|
||||
x_min, x_max = self.ax.get_xlim()
|
||||
self.pos_x_annotation = x_min + ((x_max - x_min) / 2)
|
||||
|
||||
percent = 0
|
||||
y_ecran_lim = ((max(self.ax.set_ylim()) - min(self.ax.set_ylim())) / 2)
|
||||
|
||||
if abs(y_ecran_lim) > 4:
|
||||
percent = 0.05
|
||||
elif 4 < abs(y_ecran_lim) < 1.5:
|
||||
percent = 0.01
|
||||
elif 0.5 < abs(y_ecran_lim) < 1.5:
|
||||
percent = 0.05
|
||||
elif 0.25 < abs(y_ecran_lim) < 0.5:
|
||||
percent = 0.08
|
||||
elif 0 < abs(y_ecran_lim) < 0.25:
|
||||
percent = 0.25
|
||||
else:
|
||||
percent = 0.1
|
||||
|
||||
cte = 0.
|
||||
if abs(event.ydata) < 100:
|
||||
cte = 0.05
|
||||
else:
|
||||
cte = event.y * 0.1 / 100
|
||||
|
||||
self.y_pos_text_param_hydrau = event.ydata + cte
|
||||
self.annotation_onclick.set_position((self.pos_x_annotation, self.y_pos_text_param_hydrau))
|
||||
|
||||
self.ax.callbacks.connect('ylim_changed', self.on_ylims_change)
|
||||
|
||||
self.annotation_onclick.set_color("DarkBlue")
|
||||
self.annotation_onclick.set_visible(True)
|
||||
self.annotation_onclick.set_horizontalalignment('center')
|
||||
|
||||
self.ax.figure.canvas.draw_idle()
|
||||
|
||||
return self.annotation_onclick
|
||||
|
||||
def largeur_au_miroir(self, event):
|
||||
if event.ydata <= self.z_berge_basse:
|
||||
self._largeur_miroir.set_data(
|
||||
[min(self.x), max(self.x)],
|
||||
[event.ydata, event.ydata]
|
||||
)
|
||||
else:
|
||||
self._largeur_miroir.set_data(
|
||||
[min(self.x), max(self.x)],
|
||||
[self.z_berge_basse, self.z_berge_basse]
|
||||
)
|
||||
|
||||
return self._largeur_miroir
|
||||
|
||||
def onpick(self, event):
|
||||
modifiers = QApplication.keyboardModifiers()
|
||||
|
||||
if modifiers == Qt.ControlModifier:
|
||||
if event.mouseevent.inaxes == self.ax:
|
||||
self.select_qtableview_row(event)
|
||||
x_proche, y_proche = self.point_plus_proche_ecran(event)
|
||||
self.update_select_point_point_bis(x_proche, y_proche)
|
||||
|
||||
self.ax.figure.canvas.draw_idle()
|
||||
|
||||
def onclick(self, event):
|
||||
modifiers = QtWidgets.QApplication.keyboardModifiers()
|
||||
if modifiers == Qt.ShiftModifier:
|
||||
if event.inaxes == self.ax:
|
||||
if self.z_point_bas < event.ydata:
|
||||
try:
|
||||
self.poly_col_bis.remove()
|
||||
self.largeur_au_miroir(event)
|
||||
except:
|
||||
self.largeur_au_miroir(event)
|
||||
|
||||
self.annotate_onclick(event)
|
||||
self.ax.figure.canvas.draw_idle()
|
||||
|
||||
def remplir_zone_mouillee(self, x, y1, y2):
|
||||
"""
|
||||
Args:
|
||||
x: Les coordonnées x des nœuds définissant la courbe.
|
||||
y1: points définisant le polygone à déssiner.
|
||||
y2: points définisant le polygone à déssiner.
|
||||
Returns: dessine et colorie la région définie par le polygone.
|
||||
"""
|
||||
return self.ax.fill_between(
|
||||
x, y1=y1, y2=y2, where=y1 > y2, interpolate=True,
|
||||
facecolor='skyblue', alpha=0.7
|
||||
)
|
||||
|
||||
def calcul_ligne_eau(self, val: float) -> (float, float, float):
|
||||
"""
|
||||
Args:
|
||||
val: Valeur de la cote Z à laquelle on veut caluler A , p et L.
|
||||
Returns: la valeur de la section mouillée A, du périmètre mouillé p et de la largeur au miroir L.
|
||||
"""
|
||||
largeur_miroir = 0.
|
||||
section_mouillee_totale = 0.
|
||||
perimetre_mouille_total = 0.
|
||||
|
||||
if self.z_point_bas < val <= self.z_berge_basse:
|
||||
z_eau = np.array([val] * (len(self.z_sans_rebord)))
|
||||
self.poly_col_bis = self.remplir_zone_mouillee(self.x_sans_rebord, z_eau, self.z_sans_rebord)
|
||||
liste_chemins = self.poly_col_bis.get_paths()
|
||||
couleurs = ['crimson', 'pink'] * len(liste_chemins)
|
||||
aire_calculee_shapely = None
|
||||
perimetre_mouille_total_shapely = None
|
||||
perimetre_shapely = 0.
|
||||
perim_calc = 0.
|
||||
|
||||
for polyg, coul in zip(liste_chemins, couleurs[0:len(liste_chemins)]):
|
||||
points_polygone = polyg.vertices
|
||||
xs = points_polygone[:, 0]
|
||||
ys = points_polygone[:, 1]
|
||||
|
||||
liste_points_miroir = [
|
||||
x for (x, y) in zip(xs, ys) if np.isclose(y, val)
|
||||
]
|
||||
largeur_miroir_polygone = liste_points_miroir[-2] - liste_points_miroir[0]
|
||||
largeur_miroir += largeur_miroir_polygone
|
||||
|
||||
polygone_shapely = ShapelyPolygon(points_polygone)
|
||||
aire_calculee_shapely = polygone_shapely.area
|
||||
perimetre_shapely = polygone_shapely.length
|
||||
perimetre_mouille_total_shapely = polygone_shapely.length - largeur_miroir
|
||||
liste_points_fond = [
|
||||
(x, y) for (x, y) in zip(xs, ys) if not np.isclose(y, val)
|
||||
]
|
||||
x_pt_prec, y_pt_prec = max(liste_points_miroir), val
|
||||
|
||||
perimetre = 0
|
||||
aire = 0
|
||||
|
||||
for un_point in liste_points_fond + [(min(liste_points_miroir), val)]:
|
||||
x_pt_suivant, y_pt_suivant = un_point
|
||||
perimetre += ((x_pt_prec - x_pt_suivant) ** 2 +
|
||||
(y_pt_prec - y_pt_suivant) ** 2) ** (1 / 2)
|
||||
aire += (((val - y_pt_prec) + (val - y_pt_suivant)) *
|
||||
abs(x_pt_suivant - x_pt_prec) / 2)
|
||||
x_pt_prec, y_pt_prec = x_pt_suivant, y_pt_suivant
|
||||
perim_calc = perimetre
|
||||
|
||||
perimetre_mouille_total = perimetre_shapely - largeur_miroir
|
||||
section_mouillee_totale = aire_calculee_shapely
|
||||
|
||||
return section_mouillee_totale, perimetre_mouille_total, largeur_miroir
|
||||
|
|
@ -0,0 +1,162 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
import os
|
||||
import matplotlib as mpl
|
||||
from matplotlib.backends import qt_compat
|
||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
from PyQt5.QtWidgets import QAction
|
||||
from matplotlib.backends.backend_qt5 import NavigationToolbar2QT
|
||||
from PyQt5.QtCore import pyqtSignal, QSize
|
||||
|
||||
_translate = QtCore.QCoreApplication.translate
|
||||
|
||||
file_path = os.path.abspath(os.path.dirname(__file__))
|
||||
|
||||
|
||||
class PamHyrNavigationToolbar2QT(NavigationToolbar2QT):
|
||||
"""
|
||||
Cette classe est une personnalisation de la toolbar (NavigationToolbar2QT). Elle permet l'internationnalisation et
|
||||
l'ajout d'autres boutons à la toolbar initiale
|
||||
"""
|
||||
isometric_signal = pyqtSignal(str)
|
||||
|
||||
def __init__(self, canvas, parent):
|
||||
"""
|
||||
Args:
|
||||
canvas: canvas de matplotlib
|
||||
parent: parent du canvas
|
||||
"""
|
||||
self.my_canvas = canvas
|
||||
self.toolitems = [
|
||||
(None, None, None, None),
|
||||
|
||||
('Home', _translate("Toolbar", 'Vue originale'), 'home', 'home'),
|
||||
(None, None, None, None),
|
||||
|
||||
('Back', _translate("Toolbar", 'Retour à la vue précédente'), 'back', 'back'),
|
||||
('Forward', _translate("Toolbar", 'Passer à la vue suivante'), 'forward', 'forward'),
|
||||
(None, None, None, None),
|
||||
|
||||
('Pan', _translate(
|
||||
"Toolbar",
|
||||
'Panoramique des axes avec la souris gauche, zoom avec la droite'
|
||||
), 'move', 'pan'),
|
||||
(None, None, None, None),
|
||||
|
||||
('Zoom', _translate("Toolbar", 'Zoom'), 'zoom_to_rect', 'zoom'),
|
||||
(None, None, None, None),
|
||||
|
||||
('Isometric_view', _translate(
|
||||
"Toolbar", 'Vue isométrique (Shift+W)'
|
||||
), '', 'isometric_view'),
|
||||
(None, None, None, None),
|
||||
|
||||
('GlobalView', _translate(
|
||||
"Toolbar", 'Vue globale automatique (Shift+X)'
|
||||
), '', 'non_isometric_view'),
|
||||
|
||||
(None, None, None, None),
|
||||
|
||||
('Save', _translate(
|
||||
"Toolbar", 'Enregistrer la figure'
|
||||
), 'filesave', 'save_figure'),
|
||||
(None, None, None, None),
|
||||
]
|
||||
|
||||
NavigationToolbar2QT.__init__(self, canvas, parent)
|
||||
btn_size = QSize(30, 30)
|
||||
|
||||
icon_zoom = QtGui.QIcon()
|
||||
icon_zoom.addPixmap(QtGui.QPixmap(
|
||||
f"{os.path.dirname(os.path.dirname(file_path))}/resources/icons/zoom.png"
|
||||
))
|
||||
icon_btn_isometric_view = QtGui.QIcon()
|
||||
icon_btn_isometric_view.addPixmap(
|
||||
QtGui.QPixmap(f"{os.path.dirname(os.path.dirname(file_path))}/resources"
|
||||
f"/icons/zoom_fit_11.png"))
|
||||
|
||||
icon_btn_global_view = QtGui.QIcon()
|
||||
icon_btn_global_view.addPixmap(
|
||||
QtGui.QPixmap(f"{os.path.dirname(os.path.dirname(file_path))}/resources/icons"
|
||||
f"/zoom_fit.png"))
|
||||
|
||||
actions = self.findChildren(QAction)
|
||||
self._actions["zoom"].setIcon(icon_zoom)
|
||||
self._actions["isometric_view"].setIcon(icon_btn_isometric_view)
|
||||
self._actions["non_isometric_view"].setIcon(icon_btn_global_view)
|
||||
|
||||
self.addSeparator()
|
||||
self.set_style_sheet()
|
||||
|
||||
def save_figure(self, *args):
|
||||
filetypes = self.canvas.get_supported_filetypes_grouped()
|
||||
sorted_filetypes = sorted(filetypes.items())
|
||||
default_filetype = self.canvas.get_default_filetype()
|
||||
|
||||
startpath = os.path.expanduser(mpl.rcParams['savefig.directory'])
|
||||
start = os.path.join(startpath, self.canvas.get_default_filename())
|
||||
filters = []
|
||||
selectedFilter = None
|
||||
for name, exts in sorted_filetypes:
|
||||
exts_list = " ".join(['*.%s' % ext for ext in exts])
|
||||
filter = '%s (%s)' % (name, exts_list)
|
||||
if default_filetype in exts:
|
||||
selectedFilter = filter
|
||||
filters.append(filter)
|
||||
filters = ';;'.join(filters)
|
||||
|
||||
fname, filter = qt_compat._getSaveFileName(
|
||||
self.canvas.parent(),
|
||||
_translate("MainWindow_reach", "Choisissez un nom de fichier à sauvegarder"),
|
||||
start,
|
||||
filters, selectedFilter)
|
||||
|
||||
if fname:
|
||||
if startpath != "":
|
||||
mpl.rcParams['savefig.directory'] = os.path.dirname(fname)
|
||||
|
||||
try:
|
||||
self.canvas.figure.savefig(fname)
|
||||
except Exception as e:
|
||||
QtWidgets.QMessageBox.critical(
|
||||
self, "Error saving file", str(e),
|
||||
QtWidgets.QMessageBox.Ok, QtWidgets.QMessageBox.NoButton
|
||||
)
|
||||
|
||||
def cursor1(self):
|
||||
print("TODO")
|
||||
|
||||
def isometric_view(self):
|
||||
self.my_canvas.axes.axis("equal")
|
||||
self.my_canvas.figure.canvas.draw_idle()
|
||||
self.isometric_signal[str].emit("vue iso")
|
||||
|
||||
def non_isometric_view(self):
|
||||
self.my_canvas.axes.axis("tight")
|
||||
self.my_canvas.toolbar.update()
|
||||
self.my_canvas.figure.canvas.draw_idle()
|
||||
|
||||
def toolitems_translation(self):
|
||||
self._actions['home'].setToolTip(_translate("Toolbar", "Vue originale"))
|
||||
self._actions['back'].setToolTip(_translate("Toolbar", "Retour à la vue précédente"))
|
||||
self._actions['forward'].setToolTip(_translate("Toolbar", "Passer à la vue suivante"))
|
||||
self._actions['pan'].setToolTip(_translate("Toolbar", "Panoramique des axes avec la "
|
||||
"souris gauche, zoom avec la droite"))
|
||||
self._actions['zoom'].setToolTip(_translate("Toolbar", "Zoom"))
|
||||
self._actions['save_figure'].setToolTip(_translate("Toolbar", "Enregistrer la figure"))
|
||||
self.action_isometric_view.setToolTip(_translate("Toolbar", "Vue isométrique (Shift+W)"))
|
||||
self.action_auto_global_view.setToolTip(_translate("Toolbar", "Vue globale automatique (Shift+X)"))
|
||||
|
||||
def set_style_sheet(self):
|
||||
self.setStyleSheet(
|
||||
"QToolBar{ border: 1px solid darkGray;\n"
|
||||
" gridline-color: blue;\n"
|
||||
" border-radius: 4px;\n"
|
||||
" border-style: solid;\n"
|
||||
" background-color: #EEF6FC; \n"
|
||||
" selection-background-color: #218ede;\n"
|
||||
" font-size: 12px;\n"
|
||||
" font-family: Helvetica\n"
|
||||
"\n"
|
||||
" }"
|
||||
)
|
||||
Loading…
Reference in New Issue