diff --git a/src/Scripts/MageMesh.py b/src/Scripts/MageMesh.py new file mode 100644 index 0000000000000000000000000000000000000000..065c12340b1b8a4ac2a6481d251f464acc6858b1 --- /dev/null +++ b/src/Scripts/MageMesh.py @@ -0,0 +1,289 @@ +# MageMesh.py -- Pamhyr +# Copyright (C) 2023 INRAE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +# -*- coding: utf-8 -*- + +import os +import logging + +from ctypes import ( + cdll, + byref, Structure, + c_char_p, c_wchar_p, + create_string_buffer, + POINTER, c_void_p, + c_int, c_double, c_bool +) + +from Scripts.AScript import AScript + +logger = logging.getLogger() + +bief_lib = None +c_init_bief_from_geo_file = None +c_get_nb_sections = None +c_get_nb_points_section = None +c_set_bief_name = None +c_st_to_m_compl = None +c_interpolate_profils_pas_transversal = None +c_update_pk = None +c_output_bief = None + +########################## +# Binding initialisation # +########################## + + +def init_clib(lib_path): + global bief_lib + bief_lib = cdll.LoadLibrary(lib_path) + + init_c_init_bief_from_geo_file(bief_lib) + init_c_get_nb_sections(bief_lib) + init_c_get_nb_points_section(bief_lib) + init_c_set_bief_name(bief_lib) + init_c_st_to_m_compl(bief_lib) + init_c_interpolate_profils_pas_transversal(bief_lib) + init_c_update_pk(bief_lib) + init_c_output_bief(bief_lib) + + +def init_c_init_bief_from_geo_file(bief_lib): + global c_init_bief_from_geo_file + + c_init_bief_from_geo_file = getattr( + bief_lib, 'c_init_bief_from_geo_file' + ) + c_init_bief_from_geo_file.argtypes = [ + c_char_p, POINTER(c_int), POINTER(c_int) + ] + c_init_bief_from_geo_file.restype = None + + +def init_c_get_nb_sections(bief_lib): + global c_get_nb_sections + + c_get_nb_sections = getattr(bief_lib, 'c_get_nb_sections') + c_get_nb_sections.argtypes = [POINTER(c_int)] + c_get_nb_sections.restype = None + + +def init_c_get_nb_points_section(bief_lib): + global c_get_nb_points_section + + c_get_nb_points_section = getattr(bief_lib, 'c_get_nb_points_section') + c_get_nb_points_section.argtypes = [POINTER(c_int), POINTER(c_int)] + c_get_nb_points_section.restype = None + + +def init_c_set_bief_name(bief_lib): + global c_set_bief_name + + c_set_bief_name = getattr(bief_lib, 'c_set_bief_name') + c_set_bief_name.argtypes = [c_char_p] + c_set_bief_name.restype = None + + +def init_c_st_to_m_compl(bief_lib): + global c_st_to_m_compl + + c_st_to_m_compl = getattr(bief_lib, 'c_st_to_m_compl') + c_st_to_m_compl.argtypes = [POINTER(c_int), c_char_p, c_char_p] + c_st_to_m_compl.restype = None + + +def init_c_interpolate_profils_pas_transversal(bief_lib): + global c_interpolate_profils_pas_transversal + + c_interpolate_profils_pas_transversal = getattr( + bief_lib, 'c_interpolate_profils_pas_transversal' + ) + c_interpolate_profils_pas_transversal.argtypes = [ + POINTER(c_int), POINTER(c_int), + c_char_p, c_char_p, + POINTER(c_double), POINTER(c_bool), + POINTER(c_int), POINTER(c_bool) + ] + c_interpolate_profils_pas_transversal.restype = None + + +def init_c_update_pk(bief_lib): + global c_update_pk + + c_update_pk = getattr(bief_lib, 'c_update_pk') + c_update_pk.argtypes = [c_char_p] + c_update_pk.restype = None + + +def init_c_output_bief(bief_lib): + global c_output_bief + + c_output_bief = getattr(bief_lib, 'c_output_bief') + c_output_bief.argtypes = [c_char_p] + c_output_bief.restype = None + + +def init_bief_from_geo_file(name, with_charriage, with_water): + logger.info("! call init_bief_from_geo_file:") + cname = create_string_buffer(name.encode()) + c_init_bief_from_geo_file( + cname, + byref(c_int(with_charriage)), + byref(c_int(with_water)) + ) + +##################### +# Binding functions # +##################### + + +def get_nb_sections(): + nb_sections = c_int(0) + c_get_nb_sections(byref(nb_sections)) + return nb_sections.value + + +def get_nb_points_section(section): + nb_points = c_int(0) + c_get_nb_points_section(byref(c_int(section)), byref(nb_points)) + return nb_points.value + + +def set_bief_name(name): + logger.info(f"! call set_bief_name: {repr(name)}") + cname = create_string_buffer(name.encode()) + c_set_bief_name(cname) + + +def st_to_m_compl(npoints, tag1=' ', tag2=' '): + logger.info(f"! call st_to_m_compl: {npoints}") + cnpoints = c_int(npoints) + ctag1 = create_string_buffer(tag1.encode()) + ctag2 = create_string_buffer(tag2.encode()) + + c_st_to_m_compl(byref(cnpoints), ctag1, ctag2) + + +def interpolate_profils_pas_transversal(limite1, limite2, + directrice1, directrice2, + pas, lplan=False, + lm=3, lineaire=False): + logger.info("! call interpolate_profils_pas_transversal:") + climite1 = c_int(limite1) + climite2 = c_int(limite2) + cpas = c_double(pas) + clplan = c_bool(lplan) + clm = c_int(lm) + clineaire = c_bool(lineaire) + cdirectrice1 = create_string_buffer(directrice1.encode()) + cdirectrice2 = create_string_buffer(directrice2.encode()) + + c_interpolate_profils_pas_transversal( + byref(climite1), byref(climite2), + cdirectrice1, cdirectrice2, + byref(cpas), byref(clplan), + byref(clm), byref(clineaire) + ) + + +def update_pk(directrice): + logger.info("! call update_pk:") + cdirectrice = create_string_buffer(directrice.encode()) + c_update_pk(cdirectrice) + + +def output_bief(name): + logger.info("! call output_bief:") + cname = create_string_buffer(name.encode()) + c_output_bief(cname) + + +########## +# Script # +########## + + +class MageMesh(AScript): + name = "MageMesh" + description = "Mesh ST file to M" + + def usage(self): + logger.info( + f"Usage : {self._args[0]} {self._args[1]} " + + "<SO_FILE> <ST_FILE> <STEP>" + ) + + def run(self): + if len(self._args) < 5: + return 1 + + try: + so = self._args[2] + st = self._args[3] + step = float(self._args[4]) + except Exception as e: + logger.error(f"Argument format error: {e}") + return 2 + + try: + init_clib(so) + except Exception as e: + logger.error(f"Bindings failed: {e}") + return 3 + + self.meshing(st, step) + + return 0 + + def meshing(self, st_file: str, step: float): + workdir = self.get_workdir(st_file) + file_name = st_file.rsplit(".", 1)[0] + reach_name = os.path.basename(file_name) + + # Open + init_bief_from_geo_file(st_file, 0, 0) + set_bief_name(reach_name) + + ns = get_nb_sections() + npts_max = max( + map( + lambda i: get_nb_points_section(i), + range(1, ns) + ) + ) + + # Transform + st_to_m_compl(npts_max, 'rg', 'rd') + interpolate_profils_pas_transversal( + 1, ns, + 'un', 'np', + step + ) + update_pk("un") + + # Save + logger.info(f"Saved meshing geometry to {file_name}.M") + output_bief(f"{file_name}.M") + + def get_workdir(self, file): + workdir = os.path.abspath( + os.path.dirname(file) + ) + + os.makedirs(workdir, exist_ok=True) + logger.info(f"Set working dir to {workdir}") + + return workdir diff --git a/src/View/MainWindow.py b/src/View/MainWindow.py index ac1bef1299b96168bebc1b1f60608476dc0fe32d..e48b4803ab86d0aeac5419f84a9d3c934d2b3032 100644 --- a/src/View/MainWindow.py +++ b/src/View/MainWindow.py @@ -435,7 +435,7 @@ class ApplicationWindow(QMainWindow, ListedSubWindow, WindowToolKit): "", "Pamhyr(*.pamhyr)" ) - if file_name.rsplit(".", 1)[-1] == ".pamhyr": + if file_name.rsplit(".", 1)[-1] == ".pamhyr": self._study.filename = file_name else: self._study.filename = file_name + ".pamhyr"