# -*- coding: utf-8 -*- import numpy as np from time import time from typing import List from copy import deepcopy from operator import itemgetter from Model.Geometry.Profile import Profile from Model.Geometry.ProfileXYZ import ProfileXYZ from Model.Except import FileFormatError, exception_message_box class Reach: def __init__(self, edge): self._edge = edge self._list_profiles: List[Profile] = [] def __repr__(self): return f"\n===== Début liste des profils ======> {np.array(self._list_profiles)}" \ f"\n<====== Fin liste des profils =====" @property def number_profiles(self): """ Returns: Number of profiles """ return len(self._list_profiles) def get_geometry(self) -> List[Profile]: """ Returns: The profiles list. """ return self._list_profiles def get_profile_i(self, i: int) -> Profile: """ Args: i: Index Returns: The profile at index i. """ try: return self._list_profiles[i] except IndexError: raise IndexError(f"Invalid profile index: {i}") def add_XYZ(self): """Add a new profile at the end of profiles list Returns: Nothing. """ nb_profile = self.number_profiles profile = ProfileXYZ() profile.num = nb_profile + 1 self._list_profiles.append(profile) def _update_profile_numbers(self): """Update profiles index Returns: Nothing. """ for ind, profile in enumerate(self.get_geometry()): profile.num = ind + 1 def insert(self, index: int): """Insert new profile in list Args: index: The position of the new profile. Returns: Nothing. """ profile = ProfileXYZ() self._list_profiles.insert(index, profile) self._update_profile_numbers() def delete(self, list_index: list): """Delete some elements in profile list Args: list_index: The list of element index Returns: Nothing. """ try: if list_index: indices = sorted(list(set(list_index)), reverse=True) for idx in indices: # if idx < len(self._list_profiles) : try: self._list_profiles.pop(idx) self._update_profile_numbers() except IndexError: print(f"Invalid profile index: {idx}") except TypeError: if isinstance(list_index, int): self._list_profiles.pop(list_index) self._update_profile_numbers() else: raise TypeError(f"{list_index} is instance of unexpected type '{type(list_index)}'") def _sort(self, is_reversed: bool = False): self._list_profiles = sorted( self._list_profiles, key=lambda profile: profile.kp(), reverse=is_reversed ) def sort_ascending(self): """Sort profiles by increasing KP Returns: Nothing. """ self._sort(is_reversed=False) def sort_descending(self): """Sort profiles by decreasing KP Returns: Nothing. """ self._sort(is_reversed=True) 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))) except IndexError: raise IndexError(f"Invalid profile index: {index}") def paste(self): if self.__list_copied_profiles: for profile in self.__list_copied_profiles: self._list_profiles.append(profile) def import_geometry(self, file_path_name: str): """Import a geometry from file (.ST or .st) Args: file_path_name: The absolute path of geometry file (.ST or .st) to import. Returns: Nothing. """ try: list_profile, list_header = self.read_file_st(str(file_path_name)) if list_profile and list_header: for ind, profile in enumerate(list_profile): prof = ProfileXYZ(*list_header[ind]) prof.import_points(profile) self._list_profiles.append(prof) self._update_profile_numbers() except FileNotFoundError as e: print(e) exception_message_box(e) except FileFormatError as e: print(e) e.alert() def read_file_st(self): """Read the ST file Returns: List of profiles and list of headers. """ t0 = time() line_is_header = True list_point_profile = [] list_profile = [] list_header = [] stop_code = "999.999" with open(self.file_st, encoding="utf-8") as file_st: for line in file_st: if not (line.startswith("#") or line.startswith("*")): line = line.split() if line_is_header: if len(line) >= 6: list_header.append(line[:6]) elif len(line) == 5: line.append("") list_header.append(line) else: print(f"Point {line} invalide ==> pas pris en compte") line_is_header = False else: # Read until "999.9990 999.9990" as found if len(line) == 3: x, y, z = line if stop_code in x and stop_code in y: line_is_header = True list_profile.append(list_point_profile) list_point_profile = [] else: line.append("") list_point_profile.append(line) elif len(line) == 4: x, y, z, ld = line if stop_code in x and stop_code in y: list_profile.append(list_point_profile) list_point_profile = [] line_is_header = True else: list_point_profile.append(line) else: pass if list_profile and list_header: raise FileFormatError(self.file_st, f"{list_profile}, {list_header}") print("****** Fichier {} lu et traité en {} secondes *******".format(self.file_st, time() - t0)) return list_profile, list_header