# 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 ##################### # Binding functions # ##################### 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)) ) 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(0, ' ', ' ') interpolate_profils_pas_transversal( 1, ns, 'un', 'np', step ) update_pk("un") # Save if os.path.isfile(f"{file_name}.M"): os.remove(f"{file_name}.M") 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