From cd69d56c7441e27e2367a544303a9f1d42234025 Mon Sep 17 00:00:00 2001 From: Pierre-Antoine Rouby <pierre-antoine.rouby@inrae.fr> Date: Wed, 12 Apr 2023 15:42:21 +0200 Subject: [PATCH] geometry: Guidelines computation. --- src/Model/Geometry/Profile.py | 10 +++ src/Model/Geometry/Reach.py | 106 +++++++++++++++++++++++++++- src/View/Geometry/GeometryWindow.py | 77 ++++++++++---------- src/tools.py | 19 +++++ 4 files changed, 172 insertions(+), 40 deletions(-) create mode 100644 src/tools.py diff --git a/src/Model/Geometry/Profile.py b/src/Model/Geometry/Profile.py index 1d9677bb..477e6ef5 100644 --- a/src/Model/Geometry/Profile.py +++ b/src/Model/Geometry/Profile.py @@ -91,3 +91,13 @@ class Profile(object): @profile_type.setter def profile_type(self, value: str): self._profile_type = value + + + def named_points(self): + """List of named point + + Returns: + The list of named point + """ + return [point for point in self._points + if point.point_is_named()] diff --git a/src/Model/Geometry/Reach.py b/src/Model/Geometry/Reach.py index c7492c12..6e2f0d39 100644 --- a/src/Model/Geometry/Reach.py +++ b/src/Model/Geometry/Reach.py @@ -7,6 +7,8 @@ from typing import List from copy import deepcopy from operator import itemgetter +from tools import flatten + from Model.Geometry.Profile import Profile from Model.Geometry.ProfileXYZ import ProfileXYZ @@ -17,6 +19,9 @@ class Reach: self._parent = parent self._profiles: List[Profile] = [] + self._guidelines_is_valid = False + self._guidelines = {} + # Copy/Paste self.__list_copied_profiles = [] @@ -138,7 +143,16 @@ class Reach: reverse=is_reversed ) - def z_min(self): + def get_x(self): + return [profile.x() for profile in self.profiles] + + def get_y(self): + return [profile.y() for profile in self.profiles] + + def get_z(self): + return [profile.z() for profile in self.profiles] + + def get_z_min(self): """List of z min for each profile Returns: @@ -146,7 +160,7 @@ class Reach: """ return [profile.z_min() for profile in self._data.profiles] - def z_max(self): + def get_z_max(self): """List of z max for each profile Returns: @@ -154,7 +168,7 @@ class Reach: """ return [profile.z_max() for profile in self._data.profiles] - def kp(self): + def get_kp(self): """List of profiles kp Returns: @@ -162,6 +176,92 @@ class Reach: """ return [profile.kp for profile in self._data.profiles] + ############## + # GUIDELINES # + ############## + + def _compute_guidelines_cache(self, guide_set, named_points): + # Reset guide lines cache + self._guidelines = {} + + # Make a list of point for each guideline + for guide in guide_set: + self._guidelines[guide] = flatten( + map( + lambda l: list( + # Filter point with name (we assume we have + # only one point by profile) + filter( + lambda p: p.name == guide, + l + ) + ), + named_points + ) + ) + + def compute_guidelines(self): + """Compute reach guideline and check if is valid for all profiles + + Returns: + True if all guide line is valid + """ + # Get all point contains into a guideline + named_points = [profile.named_points() for profile in self._profiles] + points_name = list( + map( + lambda lst: list(map(lambda p: p.name, lst)), + named_points + ) + ) + + # Get all guide line name + guide_set = reduce( + lambda acc, x: set(x).union(acc), + points_name + ) + + # All guide line is valid + is_ok = reduce( + bool.__and__, + map( + lambda l: len(set(l).symmetric_difference(guide_set)) == 0, + points_name + ) + ) + self._guidelines_is_valid = is_ok + + # Compute guideline and put data in cache + self._compute_guidelines_cache(guide_set, named_points) + + return is_ok + + def _map_guidelines_points(self, func): + return list( + # Map for each guideline + map( + lambda k: list( + # Apply function FUNC on each point of guideline + map( + func, + self._guidelines[k], + ) + ), + self._guidelines + ) + ) + + def get_guidelines_x(self): + return self._map_guidelines_points(lambda p: p.x) + + def get_guidelines_y(self): + return self._map_guidelines_points(lambda p: p.y) + + def get_guidelines_z(self): + return self._map_guidelines_points(lambda p: p.z) + + # Sort + def sort_ascending(self): """Sort profiles by increasing KP diff --git a/src/View/Geometry/GeometryWindow.py b/src/View/Geometry/GeometryWindow.py index 4282d7ac..a28e1f84 100644 --- a/src/View/Geometry/GeometryWindow.py +++ b/src/View/Geometry/GeometryWindow.py @@ -149,17 +149,17 @@ class GeometryWindow(QMainWindow, WindowToolKit): for selected_row in list_selected_row[:5]: selected_row = int(selected_row) profile_identifier = self._reach.get_profile_selected_identifier(selected_row) - Pk = self._reach.get_pk_i(selected_row) + Kp = self._reach.get_kp_i(selected_row) profile_name = self._reach.get_profile_name(selected_row) if len(self.list_second_window) == 0: self.second_window = window_profileXYZ.View( selected_row + 1, self._reach.get_profile_via_identifier(profile_identifier), - pk=Pk, profile_name="", parent=self + kp=Kp, profile_name="", parent=self ) self.second_window.window_title( - pk=Pk, + kp=Kp, profile_name=profile_name, profile_selected_num=selected_row ) @@ -172,7 +172,7 @@ class GeometryWindow(QMainWindow, WindowToolKit): 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, + kp=Kp, profile_name=profile_name, profile_selected_num=selected_row ) @@ -187,10 +187,10 @@ class GeometryWindow(QMainWindow, WindowToolKit): second_window1 = window_profileXYZ.View( selected_row + 1, self._reach.get_profile_via_identifier(profile_identifier), - pk=Pk, profile_name="", parent=self + kp=Kp, profile_name="", parent=self ) second_window1.window_title( - pk=Pk, profile_name=profile_name, + kp=Kp, profile_name=profile_name, profile_selected_num=selected_row ) @@ -253,14 +253,16 @@ class GeometryWindow(QMainWindow, WindowToolKit): self.plot_selected_1, = self.ui.canvas_1.axes.plot( self._reach.get_x_profile_i(0), - self._reach.get_y_profile_i(0), lw=1., markersize=3, + self._reach.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._reach.get_x_profile_i(0), - self._reach.get_y_profile_i(0), lw=1., markersize=3, + self._reach.get_y_profile_i(0), + lw=1., markersize=3, marker='+', color="k", linestyle="--" ) @@ -268,7 +270,8 @@ class GeometryWindow(QMainWindow, WindowToolKit): self.after_plot_selected_1, = self.ui.canvas_1.axes.plot( self._reach.get_x_profile_i(0), - self._reach.get_y_profile_i(0), lw=1., markersize=3, + self._reach.get_y_profile_i(0), + lw=1., markersize=3, marker='+', color="m", linestyle='--' ) @@ -284,54 +287,54 @@ class GeometryWindow(QMainWindow, WindowToolKit): 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 + _translate("MainWindow_reach", "Kp (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._reach.get_pk() + self.get_kp = self._reach.get_kp() self.get_z_min = self._reach.get_z_min() self.get_z_max = self._reach.get_z_max() - self.line_pk_zmin_zmax = self.ui.canvas_2.axes.vlines( - x=self.get_pk, + self.line_kp_zmin_zmax = self.ui.canvas_2.axes.vlines( + x=self.get_kp, 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_kp[0], self.get_kp[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_kp[0], self.get_kp[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_kp[0], self.get_kp[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.line_kp_zld = [ self.ui.canvas_2.axes.plot( - self._reach.get_pk(), i, lw=1. + self._reach.get_kp(), 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, + self.line_kp_zmin, = self.ui.canvas_2.axes.plot( + self.get_kp, self.get_z_min, linestyle=":", lw=1.8, color='lightgrey' ) @@ -363,23 +366,23 @@ class GeometryWindow(QMainWindow, WindowToolKit): def update_graphic_2(self): self.tableView.model().blockSignals(True) - get_pk = self._reach.get_pk() + get_kp = self._reach.get_kp() get_z_min = self._reach.get_z_min() get_z_max = self._reach.get_z_max() - self.line_pk_zmin.set_data(get_pk, get_z_min) + self.line_kp_zmin.set_data(get_kp, get_z_min) - self.line_pk_zmin_zmax.remove() - self.line_pk_zmin_zmax = self.ui.canvas_2.axes.vlines( - x=get_pk, + self.line_kp_zmin_zmax.remove() + self.line_kp_zmin_zmax = self.ui.canvas_2.axes.vlines( + x=get_kp, 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] + for i in range(len(self.line_kp_zld)): + self.line_kp_zld[i][0].set_data( + get_kp, self.model.z_complete_guideline()[i] ) except: print("TODO") @@ -618,12 +621,12 @@ class GeometryWindow(QMainWindow, WindowToolKit): self.tableView.model().blockSignals(False) def select_plot_graphic_2(self, ind: int): - get_pk_i = self.get_pk_i(ind) + get_kp_i = self.get_kp_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), + self.plot_selected_2.set_data((get_kp_i, get_kp_i), (get_z_min_i, get_z_max_i)) self.plot_selected_2.set_visible(True) @@ -651,12 +654,12 @@ class GeometryWindow(QMainWindow, WindowToolKit): 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_kp_i = self.get_kp_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_kp_i, get_kp_i), (get_z_min_i, get_z_max_i) ) @@ -666,12 +669,12 @@ class GeometryWindow(QMainWindow, WindowToolKit): 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_kp_i = self.get_kp_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_kp_i, get_kp_i), (get_z_min_i, get_z_max_i) ) @@ -730,11 +733,11 @@ class GeometryWindow(QMainWindow, WindowToolKit): self.ui.verticalSlider.setMaximum(self.model.rowCount() - 1) slider_value = self.ui.verticalSlider.value() - pk = self._reach.get_pk_profile_i(slider_value) + kp = self._reach.get_kp_profile_i(slider_value) self.ui.vertical_slider_label.setText( - _translate("MainWindow_reach", "Pk : ") + - f"{pk}" + "\n" + + _translate("MainWindow_reach", "Kp : ") + + f"{kp}" + "\n" + _translate("MainWindow_reach", "Profil N° : ") + f"{slider_value + 1}" diff --git a/src/tools.py b/src/tools.py new file mode 100644 index 00000000..34805ed4 --- /dev/null +++ b/src/tools.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- + +from functools import ( + reduce, partial +) + +def flatten(lst): + """Flatten list of list + + Args: + lst: A list of list + + Returns: + returns a list of element + """ + if not lst: + return [] + + return reduce(list.__add__, lst) -- GitLab