_______________________________________________________________________________________________________________________________________
/*************************************************************************************************************************************/
/*                                                                                                                                   */
/*        F O N C T I O N S   D E   B A S E   D E   G E S T I O N   D E S   C O N T O U R S  :                                       */
/*                                                                                                                                   */
/*                                                                                                                                   */
/*        Definition :                                                                                                               */
/*                                                                                                                                   */
/*                    Ce fichier contient toutes les fonctions                                                                       */
/*                  de base de calcul des contours (extraction,                                                                      */
/*                  remplissage,...) d'une images raster, quelle que                                                                 */
/*                  soit la definition.                                                                                              */
/*                                                                                                                                   */
/*                                                                                                                                   */
/*        Author of '$xiii/contours$FON' :                                                                                           */
/*                                                                                                                                   */
/*                    Jean-Francois COLONNA (LACTAMME, 19870000000000).                                                              */
/*                                                                                                                                   */
/*************************************************************************************************************************************/

/*===================================================================================================================================*/
/*************************************************************************************************************************************/
/*                                                                                                                                   */
/*        R E M P L I S S A G E   D U   V O I S I N A G E   D ' U N   P O I N T   D ' U N E   I M A G E  :                           */
/*                                                                                                                                   */
/*************************************************************************************************************************************/

BFonctionI

DEFV(Common,DEFV(Float,SINT(Iremplissage_voisinage_____increment_recursif_du_niveau_de_remplissage,FZERO)));
                                        /* Cet increment (ou decrement, suivant son signe...) permet de changer le niveau de         */
                                        /* remplissage a chaque nouveau niveau de recursivite...                                     */

DEFV(Common,DEFV(Logical,SINT(Iremplissage_voisinage_____calculer_l_histogramme_du__bord,FAUX)));
                                        /* Cet indicateur introduit le 20230823132102 permet de calculer l'histogramme du 'bord'     */
                                        /* en particulier pour savoir quel est son niveau majoritaire...                             */

DEFV(Common,DEFV(Int,SINT(Iremplissage_voisinage_____nombre_de_points_du__fond,ZERO)));
DEFV(Common,DEFV(pointF_2D,Iremplissage_voisinage_____centre_de_gravite_du__fond));
                                        /* Introduit le 20161105103427 et complete le 20161105105224 par l'edition...                */

DEFV(Common,DEFV(Logical,SINT(Iremplissage_voisinage_____calculer_la_matrice_d_inertie_du__fond,FAUX)));
DEFV(Common,DEFV(matrixF_2D,Iremplissage_voisinage_____matrice_d_inertie_du__fond));
                                        /* Donnees introduites le 20230825094226 pour calculer les moments d'inertie d'un contour.   */

DEFV(Common,DEFV(Logical,SINT(Iremplissage_voisinage_____rechercher_le_niveau_maximal_d_un_point_isole,FAUX)));
DEFV(Common,DEFV(genere_Float,SINT(Iremplissage_voisinage_____niveau_maximal_d_un_point_isole,F_MOINS_L_INFINI)));
                                        /* Afin de calculer le niveau maximal du fond (introduit le 20230827092529). On notera       */
                                        /* l'usage de 'genere_Float' et non pas de 'genere_p' afin de faciliter la recherche de      */
                                        /* ce maximum...                                                                             */

#define   TEST_REMPLISSAGE_POINT_ISOLE(direction,x,y)                                                                                   \
                    Bblock                                                                                                              \
                    Test(IL_FAUT(direction))                                                                                            \
                         Bblock                                                                                                         \
                         Test(TEST_DANS_L_IMAGE(x,y))                                                                                   \
                              Bblock                                                                                                    \
                              DEFV(genere_p,INIT(voisin,load_point(imageA,x,y)));                                                       \
                                        /* Recuperation du niveau du point courant.                                                  */ \
                                                                                                                                        \
                              INCR(nombre_de_voisins_total,I);                                                                          \
                                                                                                                                        \
                              Test(EST_VRAI(ITb1(fond,INDX(voisin,NOIR))))                                                              \
                                   Bblock                                                                                               \
                                   INCR(nombre_de_voisins_appartenant_au_fond,I);                                                       \
                                   Eblock                                                                                               \
                              ATes                                                                                                      \
                                   Bblock                                                                                               \
                                   Eblock                                                                                               \
                              ETes                                                                                                      \
                              Eblock                                                                                                    \
                         ATes                                                                                                           \
                              Bblock                                                                                                    \
                              Eblock                                                                                                    \
                         ETes                                                                                                           \
                         Eblock                                                                                                         \
                    ATes                                                                                                                \
                         Bblock                                                                                                         \
                         Eblock                                                                                                         \
                    ETes                                                                                                                \
                    Eblock

#define   MOVE_REMPLISSAGE(direction,x,y)                                                                                               \
                    Bblock                                                                                                              \
                    Test(IL_FAUT(direction))                                                                                            \
                         Bblock                                                                                                         \
                         CALS(Iremplissage_voisinage(imageR                                                                             \
                                                    ,imageA                                                                             \
                                                    ,x,y                                                                                \
                                                    ,coin_gauche,coin_droite                                                            \
                                                    ,coin_inferieur,coin_superieur                                                      \
                                                    ,fond,bord                                                                          \
                                                    ,est_______,nord______,ouest_____,sud_______                                        \
                                                    ,nord_est__,nord_ouest,sud_ouest_,sud_est___                                        \
                                                    ,ADD2(niveau_de_remplissage                                                         \
                                                         ,Iremplissage_voisinage_____increment_recursif_du_niveau_de_remplissage        \
                                                          )                                                                             \
                                                     )                                                                                  \
                              );                                                                                                        \
                         Eblock                                                                                                         \
                    ATes                                                                                                                \
                         Bblock                                                                                                         \
                         Eblock                                                                                                         \
                    ETes                                                                                                                \
                    Eblock                                                                                                              \
                                        /* Fonction de test de la necessite de faire un deplacement dans                             */ \
                                        /* une 'direction' argument, et si oui, donc, remplir le voisinage                           */ \
                                        /* du point courant dans cette direction.                                                    */

DEFV(Local,DEFV(FonctionI,Iremplissage_voisinage(imageR
                                                ,imageA
                                                ,X,Y
                                                ,coin_gauche,coin_droite
                                                ,coin_inferieur,coin_superieur
                                                ,fond,bord
                                                ,est_______,nord______,ouest_____,sud_______
                                                ,nord_est__,nord_ouest,sud_ouest_,sud_est___
                                                ,niveau_de_remplissage
                                                 )
                )
     )
DEFV(Argument,DEFV(image,imageR));
                                        /* Image Resultat contenant le remplissage du contour Argument.                              */
DEFV(Argument,DEFV(image,imageA));
                                        /* Image Argument.                                                                           */
DEFV(Argument,DEFV(Int,X));
DEFV(Argument,DEFV(Int,Y));
                                        /* Coordonnees entieres 'X' et 'Y'.                                                          */
DEFV(Argument,DEFV(Int,coin_gauche));
                                        /* Definition                                                                                */
DEFV(Argument,DEFV(Int,coin_droite));
                                        /*            du cadre                                                                       */
DEFV(Argument,DEFV(Int,coin_inferieur));
                                        /*                     a l'interieur duquel                                                  */
DEFV(Argument,DEFV(Int,coin_superieur));
                                        /*                                          se fait le remplissage.                          */
DEFV(Argument,DEFV(Logical,DTb1(fond,COULEURS)));
                                        /* Definit ainsi pour chaque niveau s'il appartient ('VRAI') ou pas                          */
                                        /* ('FAUX') au fond, c'est-a-dire a ce que l'on doit remplir.                                */
DEFV(Argument,DEFV(Logical,DTb1(bord,COULEURS)));
                                        /* Definit ainsi pour chaque niveau s'il appartient ('VRAI') ou pas                          */
                                        /* ('FAUX') au bord, c'est-a-dire a ce qui delimite le contour.                              */
DEFV(Argument,DEFV(Logical,est_______));
                                        /* Variable logique indiquant si l'on doit emprunter la direction 'est'                      */
                                        /* ('VRAI') ou pas ('FAUX') lors du parcours recursif de l'interieur                         */
                                        /* du contour.                                                                               */
DEFV(Argument,DEFV(Logical,nord______));
                                        /* Variable logique indiquant si l'on doit emprunter la direction 'nord'                     */
                                        /* ('VRAI') ou pas ('FAUX') lors du parcours recursif de l'interieur                         */
                                        /* du contour.                                                                               */
DEFV(Argument,DEFV(Logical,ouest_____));
                                        /* Variable logique indiquant si l'on doit emprunter la direction 'ouest'                    */
                                        /* ('VRAI') ou pas ('FAUX') lors du parcours recursif de l'interieur                         */
                                        /* du contour.                                                                               */
DEFV(Argument,DEFV(Logical,sud_______));
                                        /* Variable logique indiquant si l'on doit emprunter la direction 'sud'                      */
                                        /* ('VRAI') ou pas ('FAUX') lors du parcours recursif de l'interieur                         */
                                        /* du contour.                                                                               */
DEFV(Argument,DEFV(Logical,nord_est__));
                                        /* Variable logique indiquant si l'on doit emprunter la direction 'nord_est'                 */
                                        /* ('VRAI') ou pas ('FAUX') lors du parcours recursif de l'interieur                         */
                                        /* du contour.                                                                               */
DEFV(Argument,DEFV(Logical,nord_ouest));
                                        /* Variable logique indiquant si l'on doit emprunter la direction 'nord_ouest'               */
                                        /* ('VRAI') ou pas ('FAUX') lors du parcours recursif de l'interieur                         */
                                        /* du contour.                                                                               */
DEFV(Argument,DEFV(Logical,sud_ouest_));
                                        /* Variable logique indiquant si l'on doit emprunter la direction 'sud_ouest'                */
                                        /* ('VRAI') ou pas ('FAUX') lors du parcours recursif de l'interieur                         */
                                        /* du contour.                                                                               */
DEFV(Argument,DEFV(Logical,sud_est___));
                                        /* Variable logique indiquant si l'on doit emprunter la direction 'sud_est'                  */
DEFV(Argument,DEFV(genere_Float,niveau_de_remplissage));
                                        /* Niveau a utiliser pour remplir le contour Argument.                                       */
/*-----------------------------------------------------------------------------------------------------------------------------------*/
     Bblock
     INIT_ERROR;
                                        /* ATTENTION : 'INIT_ERROR' est mis en tete des variables locales au cas ou des couples      */
                                        /* ('BDEFV','EDEFV') suivraient...                                                           */
     /*..............................................................................................................................*/
     Test(IFET(TEST_DANS_L_IMAGE(X,Y)
              ,IFET(INCLff(X,coin_gauche,coin_droite)
                   ,INCLff(Y,coin_inferieur,coin_superieur)
                    )
               )
          )
          Bblock
          Test(TEST_POINT_NON_MARQUE(X,Y))
               Bblock
                                        /* On ne traite que les points sur lesquels on n'est pas encore passe ; on                   */
                                        /* notera qu'il serait imprudent de tester 'NIVEAU_DE_MARQUAGE' avec                         */
                                        /* un 'IFEQ' a cause des problemes lies aux 'liste de substitution'.                         */
               DEFV(genere_p,INIT(point,load_point(imageA,X,Y)));
                                        /* Recuperation du niveau du point courant.                                                  */

               Test(IL_FAUT(Iremplissage_voisinage_____rechercher_le_niveau_maximal_d_un_point_isole))
                    Bblock
                    Test(EST_FAUX(ITb1(fond,INDX(point,NOIR))))
                         Bblock
                         DEFV(Int,INIT(nombre_de_voisins_total,ZERO));
                         DEFV(Int,INIT(nombre_de_voisins_appartenant_au_fond,ZERO));

                         TEST_REMPLISSAGE_POINT_ISOLE(est_______,SUCX(X),NEUT(Y));
                         TEST_REMPLISSAGE_POINT_ISOLE(nord______,NEUT(X),SUCY(Y));
                         TEST_REMPLISSAGE_POINT_ISOLE(ouest_____,PREX(X),NEUT(Y));
                         TEST_REMPLISSAGE_POINT_ISOLE(sud_______,NEUT(X),PREY(Y));
                         TEST_REMPLISSAGE_POINT_ISOLE(nord_est__,SUCX(X),SUCY(Y));
                         TEST_REMPLISSAGE_POINT_ISOLE(nord_ouest,PREX(X),SUCY(Y));
                         TEST_REMPLISSAGE_POINT_ISOLE(sud_ouest_,PREX(X),PREY(Y));
                         TEST_REMPLISSAGE_POINT_ISOLE(sud_est___,SUCX(X),PREY(Y));

                         Test(IFEQ(nombre_de_voisins_appartenant_au_fond,nombre_de_voisins_total))
                                        /* Le point courant {X,Y} n'est pas du 'fond' et n'a pas de voisin, il est donc isole :      */
                              Bblock
                              EGAL(Iremplissage_voisinage_____niveau_maximal_d_un_point_isole
                                  ,MAX2(Iremplissage_voisinage_____niveau_maximal_d_un_point_isole,FLOT(point))
                                   );
                              Eblock
                         ATes
                              Bblock
                              Eblock
                         ETes
                         Eblock
                    ATes
                         Bblock
                         Eblock
                    ETes
                    Eblock
               ATes
                    Bblock
                    Eblock
               ETes

               Test(EST_FAUX(ITb1(bord,INDX(point,NOIR))))
                    Bblock
                    MARQUAGE_POINT(X,Y);
                                        /* Marquage systematique des points qui ne sont pas au bord dans une image                   */
                                        /* de travail, afin d'eviter des "trous" crees par exemple lorsque les                       */
                                        /* listes de "bord" et de "fond" ne sont pas complementaires.                                */
                    Test(EST_VRAI(ITb1(fond,INDX(point,NOIR))))
                         Bblock
                                        /* Traitement des points qui n'appartiennent pas au "bord", et                               */
                                        /* qui appartiennent au "fond".                                                              */
                         Test(TEST_MASQUE_ACTIF(X,Y,MASQUER_PARCOURS))
                              Bblock
                              store_point(GENP(TRNP(niveau_de_remplissage)),imageR,X,Y,FVARIABLE);
                                        /* Finalement, remplissage du point courant {X,Y} qui appartient au "fond",                  */
                                        /* n'appartient pas au "bord" et n'est pas masque (ou bien l'est, mais                       */
                                        /* est compatible avec le seuil et la portee du masquage...).                                */

                              Test(IL_NE_FAUT_PAS(Iremplissage_voisinage_____calculer_la_matrice_d_inertie_du__fond))
                                   Bblock
                                   INCR(Iremplissage_voisinage_____nombre_de_points_du__fond,I);
                                        /* Comptage des points (introduit le 20161105103427).                                        */
                                   INCR(ASD1(Iremplissage_voisinage_____centre_de_gravite_du__fond,x),FLOT(X));
                                   INCR(ASD1(Iremplissage_voisinage_____centre_de_gravite_du__fond,y),FLOT(Y));
                                        /* Calcul "iteratif" du centre de gravite (introduit le 20161105103427).                     */
                                   Eblock
                              ATes
                                   Bblock
                                   INCR(ASD2(Iremplissage_voisinage_____matrice_d_inertie_du__fond,cx,cx)
                                       ,MUL2(SOUS(X,ASD1(Iremplissage_voisinage_____centre_de_gravite_du__fond,x))
                                            ,SOUS(X,ASD1(Iremplissage_voisinage_____centre_de_gravite_du__fond,x))
                                             )
                                        );
                                   INCR(ASD2(Iremplissage_voisinage_____matrice_d_inertie_du__fond,cx,cy)
                                       ,MUL2(SOUS(X,ASD1(Iremplissage_voisinage_____centre_de_gravite_du__fond,x))
                                            ,SOUS(Y,ASD1(Iremplissage_voisinage_____centre_de_gravite_du__fond,y))
                                             )
                                        );
                                   INCR(ASD2(Iremplissage_voisinage_____matrice_d_inertie_du__fond,cy,cx)
                                       ,MUL2(SOUS(Y,ASD1(Iremplissage_voisinage_____centre_de_gravite_du__fond,y))
                                            ,SOUS(X,ASD1(Iremplissage_voisinage_____centre_de_gravite_du__fond,x))
                                             )
                                        );
                                        /* On notera que les moments {cx,cy} et {cy,cx} sont evidemment egaux, mais qu'on les        */
                                        /* calcule malgre tout independemment l'un de l'autre pour des raisons de symetrie...        */
                                   INCR(ASD2(Iremplissage_voisinage_____matrice_d_inertie_du__fond,cy,cy)
                                       ,MUL2(SOUS(Y,ASD1(Iremplissage_voisinage_____centre_de_gravite_du__fond,y))
                                            ,SOUS(Y,ASD1(Iremplissage_voisinage_____centre_de_gravite_du__fond,y))
                                             )
                                        );
                                   Eblock
                              ETes
                              Eblock
                         ATes
                              Bblock
                              Eblock
                         ETes
                         Eblock
                    ATes
                         Bblock
                         Eblock
                    ETes

                                        /* Puis, on passe aux voisins, suivant la regle de connexite demandee.                       */
                    MOVE_REMPLISSAGE(est_______,SUCX(X),NEUT(Y));
                    MOVE_REMPLISSAGE(nord______,NEUT(X),SUCY(Y));
                    MOVE_REMPLISSAGE(ouest_____,PREX(X),NEUT(Y));
                    MOVE_REMPLISSAGE(sud_______,NEUT(X),PREY(Y));
                    MOVE_REMPLISSAGE(nord_est__,SUCX(X),SUCY(Y));
                    MOVE_REMPLISSAGE(nord_ouest,PREX(X),SUCY(Y));
                    MOVE_REMPLISSAGE(sud_ouest_,PREX(X),PREY(Y));
                    MOVE_REMPLISSAGE(sud_est___,SUCX(X),PREY(Y));
                    Eblock
               ATes
                    Bblock
                    Test(IL_FAUT(Iremplissage_voisinage_____calculer_l_histogramme_du__bord))
                         Bblock
                         INCR(ACCES_HISTOGRAMME(point),I);
                                        /* Le niveau 'point' fait partie du 'bord'...                                                */
                         Eblock
                    ATes
                         Bblock
                         Eblock
                    ETes
                    Eblock
               ETes
               Eblock
          ATes
               Bblock
               Eblock
          ETes
          Eblock
     ATes
          Bblock
          Eblock
     ETes

     RETU_ERROR;
     Eblock

#undef    MOVE_REMPLISSAGE
#undef    TEST_REMPLISSAGE_POINT_ISOLE

EFonctionI

/*===================================================================================================================================*/
/*************************************************************************************************************************************/
/*                                                                                                                                   */
/*        R E M P L I S S A G E   R E C U R S I F   D ' U N   C O N T O U R   D ' U N E   I M A G E  :                               */
/*                                                                                                                                   */
/*************************************************************************************************************************************/

BFonctionP

DEFV(Common,DEFV(Logical,SINT(Iremplissage_____editer_le_centre_de_gravite,FAUX)));
                                        /* Introduit le 20161105105224...                                                            */
DEFV(Common,DEFV(Logical,SINT(Iremplissage_____calculer_l_histogramme_du__bord,FAUX)));
                                        /* Introduit le 20230823132102...                                                            */
DEFV(Common,DEFV(Logical,SINT(Iremplissage_____editer_la_matrice_d_inertie,FAUX)));
                                        /* Introduit le 20230825094226...                                                            */

DEFV(Common,DEFV(FonctionP,POINTERp(Iremplissage(imageR
                                                ,imageA
                                                ,ARGUMENT_POINTERs(point_de_depart)
                                                ,ARGUMENT_POINTERs(coin_inferieur_gauche)
                                                ,ARGUMENT_POINTERs(coin_superieur_droite)
                                                ,fond,bord
                                                ,est_______,nord______,ouest_____,sud_______
                                                ,nord_est__,nord_ouest,sud_ouest_,sud_est___
                                                ,niveau_de_remplissage
                                                 )
                                    )
                 )
     )
DEFV(Argument,DEFV(image,imageR));
                                        /* Image Resultat contenant le remplissage du contour Argument.                              */
DEFV(Argument,DEFV(image,imageA));
                                        /* Image Argument.                                                                           */
DEFV(Argument,DEFV(pointF_2D,POINTERs(point_de_depart)));
                                        /* Coordonnees du point de depart de remplissage exprimees dans des                          */
                                        /* unites telles que l'unite vaut respectivement [Xmin,Xmax] et                              */
                                        /* [Ymin,Ymax].                                                                              */
DEFV(Argument,DEFV(pointF_2D,POINTERs(coin_inferieur_gauche)));
                                        /* Le remplissage ne sera fait qu'a l'interieur d'un "cadre" que l'on                        */
                                        /* definit par son coin inferieur gauche,                                                    */
DEFV(Argument,DEFV(pointF_2D,POINTERs(coin_superieur_droite)));
                                        /* Definit par son coin superieur droit  ; ainsi, on pourra remplir                          */
                                        /* des contours ouverts dont le "cadre" proviendra du "cadre" defini                         */
                                        /* lors du trace des vecteurs 2D.                                                            */
DEFV(Argument,DEFV(Logical,DTb1(fond,COULEURS)));
                                        /* Definit ainsi pour chaque niveau s'il appartient ('VRAI') ou pas                          */
                                        /* ('FAUX') au fond, c'est-a-dire a ce que l'on doit remplir.                                */
DEFV(Argument,DEFV(Logical,DTb1(bord,COULEURS)));
                                        /* Definit ainsi pour chaque niveau s'il appartient ('VRAI') ou pas                          */
                                        /* ('FAUX') au bord, c'est-a-dire a ce qui delimite le contour.                              */
DEFV(Argument,DEFV(Logical,est_______));
                                        /* Variable logique indiquant si l'on doit emprunter la direction 'est'                      */
                                        /* ('VRAI') ou pas ('FAUX') lors du parcours recursif de l'interieur                         */
                                        /* du contour.                                                                               */
DEFV(Argument,DEFV(Logical,nord______));
                                        /* Variable logique indiquant si l'on doit emprunter la direction 'nord'                     */
                                        /* ('VRAI') ou pas ('FAUX') lors du parcours recursif de l'interieur                         */
                                        /* du contour.                                                                               */
DEFV(Argument,DEFV(Logical,ouest_____));
                                        /* Variable logique indiquant si l'on doit emprunter la direction 'ouest'                    */
                                        /* ('VRAI') ou pas ('FAUX') lors du parcours recursif de l'interieur                         */
                                        /* du contour.                                                                               */
DEFV(Argument,DEFV(Logical,sud_______));
                                        /* Variable logique indiquant si l'on doit emprunter la direction 'sud'                      */
                                        /* ('VRAI') ou pas ('FAUX') lors du parcours recursif de l'interieur                         */
                                        /* du contour.                                                                               */
DEFV(Argument,DEFV(Logical,nord_est__));
                                        /* Variable logique indiquant si l'on doit emprunter la direction 'nord_est'                 */
                                        /* ('VRAI') ou pas ('FAUX') lors du parcours recursif de l'interieur                         */
                                        /* du contour.                                                                               */
DEFV(Argument,DEFV(Logical,nord_ouest));
                                        /* Variable logique indiquant si l'on doit emprunter la direction 'nord_ouest'               */
                                        /* ('VRAI') ou pas ('FAUX') lors du parcours recursif de l'interieur                         */
                                        /* du contour.                                                                               */
DEFV(Argument,DEFV(Logical,sud_ouest_));
                                        /* Variable logique indiquant si l'on doit emprunter la direction 'sud_ouest'                */
                                        /* ('VRAI') ou pas ('FAUX') lors du parcours recursif de l'interieur                         */
                                        /* du contour.                                                                               */
DEFV(Argument,DEFV(Logical,sud_est___));
                                        /* Variable logique indiquant si l'on doit emprunter la direction 'sud_est'                  */
                                        /* ('VRAI') ou pas ('FAUX') lors du parcours recursif de l'interieur                         */
                                        /* du contour.                                                                               */
DEFV(Argument,DEFV(genere_p,niveau_de_remplissage));
                                        /* Niveau a utiliser pour remplir le contour Argument.                                       */
/*-----------------------------------------------------------------------------------------------------------------------------------*/
     Bblock
     DEFV(Int,INIT(X,UNDEF));
     DEFV(Int,INIT(Y,UNDEF));
                                        /* Coordonnees entieres 'X' et 'Y'.                                                          */
     /*..............................................................................................................................*/
     BoIn(niveau,NOIR,BLANC,PAS_COULEURS)
          Bblock
          Test(IFEQ(ITb1(bord,INDX(niveau,NOIR)),ITb1(fond,INDX(niveau,NOIR))))
               Bblock
               PRINT_ERREUR("un niveau ne peut appartenir a la fois au 'bord' et au 'fond'");
               CAL1(Prer1("ce niveau est %08X\n",niveau));
               Eblock
          ATes
               Bblock
               Eblock
          ETes
          Eblock
     EBoI

     Test(IL_FAUT(Iremplissage_____calculer_l_histogramme_du__bord))
                                        /* Possibilite introduite le 20230823132102...                                               */
          Bblock
          BoIn(niveau,NOIR,BLANC,PAS_COULEURS)
               Bblock
               CLIR(ACCES_HISTOGRAMME(niveau));
               Eblock
          EBoI
          Eblock
     ATes
          Bblock
          Eblock
     ETes

     EGAL(Iremplissage_voisinage_____niveau_maximal_d_un_point_isole,F_MOINS_L_INFINI);
                                        /* Afin de calculer le niveau maximal du fond (introduit le 20230827092529), si besoin est.  */

     BSaveModifyVariable(Logical
                        ,Iremplissage_voisinage_____calculer_l_histogramme_du__bord
                        ,Iremplissage_____calculer_l_histogramme_du__bord
                         );
                                        /* Pour des raisons d'imbrication, ce 'BSaveModifyVariable(...)' ne peut pas etre situe      */
                                        /* dans le 'Test(IL_FAUT(Iremplissage_____calculer_l_histogramme_du__bord))' precedent...    */

     MARQUAGE_VALIDATION_ET_INITIALISATION;
                                        /* On verifie que le marquage est possible...                                                */

     EGAL(X,_cDENORMALISE_OX(ASI1(point_de_depart,x)));
     EGAL(Y,_cDENORMALISE_OY(ASI1(point_de_depart,y)));
                                        /* Recuperation des coordonnees du point de depart, et mise dans                             */
                                        /* les coordonnees de l'image.                                                               */

     Test(IL_FAUT(Iremplissage_voisinage_____calculer_la_matrice_d_inertie_du__fond))
          Bblock
          Test(IZEQ(Iremplissage_voisinage_____nombre_de_points_du__fond))
               Bblock
               PRINT_ERREUR("la matrice d'inertie ne peut etre calculee tant que le centre de gravite n'est pas connu");

               EGAL(Iremplissage_voisinage_____calculer_la_matrice_d_inertie_du__fond,FAUX);
               Eblock
          ATes
               Bblock
               Eblock
          ETes
          Eblock
     ATes
          Bblock
          Eblock
     ETes

     Test(IL_NE_FAUT_PAS(Iremplissage_voisinage_____calculer_la_matrice_d_inertie_du__fond))
                                        /* Ce test ne peut etre combine au precedent car, en effet, le test precedent peut modifier  */
                                        /* l'indicateur 'Iremplissage_voisinage_____calculer_la_matrice_d_inertie_du__fond'...       */
          Bblock
          CLIR(Iremplissage_voisinage_____nombre_de_points_du__fond);
          CLIR(ASD1(Iremplissage_voisinage_____centre_de_gravite_du__fond,x));
          CLIR(ASD1(Iremplissage_voisinage_____centre_de_gravite_du__fond,y));
                                        /* Initialisations diverses...                                                               */
          Eblock
     ATes
          Bblock
          CLIR(ASD2(Iremplissage_voisinage_____matrice_d_inertie_du__fond,cx,cx));
          CLIR(ASD2(Iremplissage_voisinage_____matrice_d_inertie_du__fond,cx,cy));
          CLIR(ASD2(Iremplissage_voisinage_____matrice_d_inertie_du__fond,cy,cx));
          CLIR(ASD2(Iremplissage_voisinage_____matrice_d_inertie_du__fond,cy,cy));
                                        /* Initialisations diverses...                                                               */
          Eblock
     ETes

     CALS(Iremplissage_voisinage(imageR
                                ,imageA
                                ,X,Y
                                ,_cDENORMALISE_OX(ASI1(coin_inferieur_gauche,x)),_cDENORMALISE_OX(ASI1(coin_superieur_droite,x))
                                ,_cDENORMALISE_OY(ASI1(coin_inferieur_gauche,y)),_cDENORMALISE_OY(ASI1(coin_superieur_droite,y))
                                ,fond,bord
                                ,est_______,nord______,ouest_____,sud_______
                                ,nord_est__,nord_ouest,sud_ouest_,sud_est___
                                ,CASP_Float(niveau_de_remplissage)
                                 )
          );
                                        /* Et remplissage recursif, voisinage par voisinage a partir                                 */
                                        /* du point de depart argument...                                                            */
                                        /*                                                                                           */
                                        /* La procedure 'CASP_Float(...)' a remplace un 'CASP(genere_Float,...)' le 20090331104759.  */

     Test(IZNE(Iremplissage_voisinage_____nombre_de_points_du__fond))
          Bblock
          Test(IL_NE_FAUT_PAS(Iremplissage_voisinage_____calculer_la_matrice_d_inertie_du__fond))
               Bblock
               EGAL(ASD1(Iremplissage_voisinage_____centre_de_gravite_du__fond,x)
                   ,DIVI(ASD1(Iremplissage_voisinage_____centre_de_gravite_du__fond,x)
                        ,FLOT(Iremplissage_voisinage_____nombre_de_points_du__fond)
                         )
                    );
               EGAL(ASD1(Iremplissage_voisinage_____centre_de_gravite_du__fond,y)
                   ,DIVI(ASD1(Iremplissage_voisinage_____centre_de_gravite_du__fond,y)
                        ,FLOT(Iremplissage_voisinage_____nombre_de_points_du__fond)
                         )
                    );
                                        /* Calcul "final" du centre de gravite (introduit le 20161105103427).                        */

               Test(IL_FAUT(Iremplissage_____editer_le_centre_de_gravite))
                    Bblock
                    CAL3(Prme1("NombreDePoints=%d\n"
                              ,Iremplissage_voisinage_____nombre_de_points_du__fond
                               )
                         );
                    CAL3(Prme2("XG=%+.^^^ YG=%+.^^^\n"
                              ,ASD1(Iremplissage_voisinage_____centre_de_gravite_du__fond,x)
                              ,ASD1(Iremplissage_voisinage_____centre_de_gravite_du__fond,y)
                               )
                         );
                                        /* Edition introduite le 20161105105224...                                                   */
                    Eblock
               ATes
                    Bblock
                    Eblock
               ETes
               Eblock
          ATes
               Bblock
               EGAL(ASD2(Iremplissage_voisinage_____matrice_d_inertie_du__fond,cx,cx)
                   ,DIVI(ASD2(Iremplissage_voisinage_____matrice_d_inertie_du__fond,cx,cx)
                        ,FLOT(Iremplissage_voisinage_____nombre_de_points_du__fond)
                         )
                    );
               EGAL(ASD2(Iremplissage_voisinage_____matrice_d_inertie_du__fond,cx,cy)
                   ,DIVI(ASD2(Iremplissage_voisinage_____matrice_d_inertie_du__fond,cx,cy)
                        ,FLOT(Iremplissage_voisinage_____nombre_de_points_du__fond)
                         )
                    );
               EGAL(ASD2(Iremplissage_voisinage_____matrice_d_inertie_du__fond,cy,cx)
                   ,DIVI(ASD2(Iremplissage_voisinage_____matrice_d_inertie_du__fond,cy,cx)
                        ,FLOT(Iremplissage_voisinage_____nombre_de_points_du__fond)
                         )
                    );
               EGAL(ASD2(Iremplissage_voisinage_____matrice_d_inertie_du__fond,cy,cy)
                   ,DIVI(ASD2(Iremplissage_voisinage_____matrice_d_inertie_du__fond,cy,cy)
                        ,FLOT(Iremplissage_voisinage_____nombre_de_points_du__fond)
                         )
                    );
                                        /* Calcul "final" de la matrice d'inertie (introduit le 20230825094226).                     */

               Test(IL_FAUT(Iremplissage_____editer_la_matrice_d_inertie))
                    Bblock
                    CAL3(Prme1("NombreDePoints=%d\n"
                              ,Iremplissage_voisinage_____nombre_de_points_du__fond
                               )
                         );
                    CAL3(Prme4("MatriceInertie={{%+.^^^,%+.^^^},{%+.^^^,%+.^^^}}\n"
                              ,ASD2(Iremplissage_voisinage_____matrice_d_inertie_du__fond,cx,cx)
                              ,ASD2(Iremplissage_voisinage_____matrice_d_inertie_du__fond,cx,cy)
                              ,ASD2(Iremplissage_voisinage_____matrice_d_inertie_du__fond,cy,cx)
                              ,ASD2(Iremplissage_voisinage_____matrice_d_inertie_du__fond,cy,cy)
                               )
                         );
                                        /* Edition introduite le 20230825094226...                                                   */
                    Eblock
               ATes
                    Bblock
                    Eblock
               ETes
               Eblock
          ETes
          Eblock
     ATes
          Bblock
          EGAL(ASD1(Iremplissage_voisinage_____centre_de_gravite_du__fond,x),FLOT(X));
          EGAL(ASD1(Iremplissage_voisinage_____centre_de_gravite_du__fond,y),FLOT(Y));
                                        /* Dans ce cas, le centre de gravite (qui n'existe en fait pas) est le point de depart       */
                                        /* {X,Y} (introduit le 20161105120709...).                                                   */
          Eblock
     ETes

     ESaveModifyVariable(Logical
                        ,Iremplissage_voisinage_____calculer_l_histogramme_du__bord
                         );
                                        /* Pour des raisons d'imbrication, ce 'ESaveModifyVariable(...)' ne peut pas etre situe      */
                                        /* dans un 'Test(IL_FAUT(Iremplissage_____calculer_l_histogramme_du__bord))'...              */
     RETI(imageR);
     Eblock

EFonctionP

/*===================================================================================================================================*/
/*************************************************************************************************************************************/
/*                                                                                                                                   */
/*        E X T R A C T I O N   D E   T O U S   L E S   P O I N T S   D E   D E P A R T   P O T E N T I E L S                        */
/*        D ' U N   R E M P L I S S A G E   D E   C O N T O U R   A   L ' E X C L U S I O N   D ' U N                                */
/*        N I V E A U   D I T   D E   ' N O N   M A R Q U A G E '  :                                                                 */
/*                                                                                                                                   */
/*************************************************************************************************************************************/

BFonctionI

DEFV(Common,DEFV(FonctionI,Ipoints_de_depart(liste_des_points_de_depart
                                            ,zones_remplies
                                            ,imageA
                                            ,est_______,nord______,ouest_____,sud_______
                                            ,nord_est__,nord_ouest,sud_ouest_,sud_est___
                                            ,largeur_de_bande
                                            ,niveau_de_non_marquage
                                             )
                 )
     )
DEFV(Argument,DEFV(image,liste_des_points_de_depart));
                                        /* Image Resultat contenant les points de depart des remplissage.                            */
DEFV(Argument,DEFV(image,zones_remplies));
                                        /* Image Resultat contenant les remplissages generes...                                      */
DEFV(Argument,DEFV(image,imageA));
                                        /* Image Argument.                                                                           */
DEFV(Argument,DEFV(Logical,est_______));
                                        /* Variable logique indiquant si l'on doit emprunter la direction 'est'                      */
                                        /* ('VRAI') ou pas ('FAUX') lors du parcours recursif de l'interieur                         */
                                        /* du contour.                                                                               */
DEFV(Argument,DEFV(Logical,nord______));
                                        /* Variable logique indiquant si l'on doit emprunter la direction 'nord'                     */
                                        /* ('VRAI') ou pas ('FAUX') lors du parcours recursif de l'interieur                         */
                                        /* du contour.                                                                               */
DEFV(Argument,DEFV(Logical,ouest_____));
                                        /* Variable logique indiquant si l'on doit emprunter la direction 'ouest'                    */
                                        /* ('VRAI') ou pas ('FAUX') lors du parcours recursif de l'interieur                         */
                                        /* du contour.                                                                               */
DEFV(Argument,DEFV(Logical,sud_______));
                                        /* Variable logique indiquant si l'on doit emprunter la direction 'sud'                      */
                                        /* ('VRAI') ou pas ('FAUX') lors du parcours recursif de l'interieur                         */
                                        /* du contour.                                                                               */
DEFV(Argument,DEFV(Logical,nord_est__));
                                        /* Variable logique indiquant si l'on doit emprunter la direction 'nord_est'                 */
                                        /* ('VRAI') ou pas ('FAUX') lors du parcours recursif de l'interieur                         */
                                        /* du contour.                                                                               */
DEFV(Argument,DEFV(Logical,nord_ouest));
                                        /* Variable logique indiquant si l'on doit emprunter la direction 'nord_ouest'               */
                                        /* ('VRAI') ou pas ('FAUX') lors du parcours recursif de l'interieur                         */
                                        /* du contour.                                                                               */
DEFV(Argument,DEFV(Logical,sud_ouest_));
                                        /* Variable logique indiquant si l'on doit emprunter la direction 'sud_ouest'                */
                                        /* ('VRAI') ou pas ('FAUX') lors du parcours recursif de l'interieur                         */
                                        /* du contour.                                                                               */
DEFV(Argument,DEFV(Logical,sud_est___));
                                        /* Variable logique indiquant si l'on doit emprunter la direction 'sud_est'                  */
                                        /* ('VRAI') ou pas ('FAUX') lors du parcours recursif de l'interieur                         */
                                        /* du contour.                                                                               */
DEFV(Argument,DEFV(Int,largeur_de_bande));
                                        /* Lorsque l'on trouve un point {X,Y} non encore marque (dans 'zones_remplies'), on          */
                                        /* l'utilise comme point de depart pour un remplissage de contour ; sont consideres          */
                                        /* comme a remplir, les points dont les niveaux sont dans l'intervalle [N-L,N+L],            */
                                        /* ou 'N' designe le niveau du point {X,Y} dans 'imageA', et 'L' la                          */
                                        /* 'largeur_de_bande' ('ZERO' donnera le plus de finesse...).                                */
DEFV(Argument,DEFV(genere_p,niveau_de_non_marquage));
                                        /* Niveau destine a marquer dans 'zones_remplies' les points non encore                      */
                                        /* rencontres ; il correspond aussi aux points de 'imageA' qui sont ignores.                 */
/*-----------------------------------------------------------------------------------------------------------------------------------*/
     Bblock
     INIT_ERROR;
                                        /* ATTENTION : 'INIT_ERROR' est mis en tete des variables locales au cas ou des couples      */
                                        /* ('BDEFV','EDEFV') suivraient...                                                           */
     DEFV(genere_p,INIT(niveau_du_point_courant,NIVEAU_UNDEF));
                                        /* Niveau du point courant {X,Y}.                                                            */
     DEFV(pointF_2D,point_de_depart);
     DEFV(pointF_2D,coin_inferieur_gauche);
                                        /* Coin inferieur gauche de la zone de remplissage,                                          */
     DEFV(pointF_2D,coin_superieur_droite);
                                        /* Coin superieur droite de la zone de remplissage.                                          */
     DEFV(Logical,DTb1(fond,COULEURS));
                                        /* Pour definir le fond courant, et                                                          */
     DEFV(Logical,DTb1(bord,COULEURS));
                                        /* Pour definir le bord courant.                                                             */
     /*..............................................................................................................................*/
     MISE_A_L_ETAT_INITIAL_LISTE_DE_SUBSTITUTION;
                                        /* Lorsque la liste de substitution n'a pas ete encore initialisee,                          */
                                        /* on le fait avant la validation...                                                         */
     CALS(Inoir(liste_des_points_de_depart));
                                        /* Nettoyage de la liste des points de depart.                                               */
     PUSH_FILTRAGE;
                                        /* Sauvegarde de l'etat courant du filtrage des niveaux.                                     */
     SET_FILTRAGE(ACTIF);
                                        /* On autorise tous les filtrages afin d'avoir la 'SUBSTITUTION'.                            */
     PUSH_SUBSTITUTION;
                                        /* Sauvegarde de la substitution courante.                                                   */

     BoIn(index_des_listes,NOIR,BLANC,PAS_COULEURS)
          Bblock
          Test(IFNE(index_des_listes,niveau_de_non_marquage))
               Bblock
               Test(IFEQ(Nsubstitution(GENP(index_des_listes)),niveau_de_non_marquage))
                    Bblock
                    PRINT_ERREUR("le 'niveau_de_non_marquage' et la 'liste de substitution' courante sont incompatibles");
                    Eblock
               ATes
                    Bblock
                    Eblock
               ETes
               Eblock
          ATes
               Bblock
               Eblock
          ETes
          Eblock
     EBoI

     PULL_SUBSTITUTION;
     PULL_FILTRAGE;
                                        /* Et restauration des conditions initiales...                                               */
     CALS(Iinitialisation(zones_remplies,niveau_de_non_marquage));
                                        /* On n'a encore marque aucun point...                                                       */
     INITIALISATION_POINT_2D(coin_inferieur_gauche
                            ,CADRE_GAUCHE
                            ,CADRE_INFERIEUR
                             );
                                        /* Definition du coin inferieur gauche de remplissage,                                       */
     INITIALISATION_POINT_2D(coin_superieur_droite
                            ,CADRE_DROITE
                            ,CADRE_SUPERIEUR
                             );
                                        /* Definition du coin superieur droite de remplissage.                                       */

     begin_image
          Bblock
          Test(IFEQ(load_point(zones_remplies,X,Y),niveau_de_non_marquage))
               Bblock
                                        /* On ne s'interesse qu'au point qui n'ont pas ete atteint lors d'un                         */
                                        /* remplissage avec un point de depart anterieur...                                          */
               EGAL(niveau_du_point_courant,load_point(imageA,X,Y));
                                        /* Recuperation du niveau du point courant dans l'image Argument.                            */

               Test(IFNE(niveau_du_point_courant,niveau_de_non_marquage))
                    Bblock
                                        /* On ne s'interesse qu'au point de 'imageA' qui sont non marques, et ce                     */
                                        /* afin que les tests qui sont faits dans 'zones_remplies' fonctionnent                      */
                                        /* correctement...                                                                           */
                    store_point(niveau_du_point_courant,liste_des_points_de_depart,X,Y,FVARIABLE);
                                        /* Et on memorise ce point...                                                                */

                    INITIALISATION_POINT_2D(point_de_depart
                                           ,_____cNORMALISE_OX(X)
                                           ,_____cNORMALISE_OY(Y)
                                            );
                                        /* Et il devient un nouveau point de depart. ATTENTION, avant le 19990602152323, il y avait  */
                                        /* ici pour des raisons obscures (et en fait surement historiques) :                         */
                                        /*                                                                                           */
                                        /*                  INITIALISATION_POINT_2D(point_de_depart                                  */
                                        /*                                         ,DIVI(FLOT(X),FLOT(dimX))                         */
                                        /*                                         ,DIVI(FLOT(Y),FLOT(dimY))                         */
                                        /*                                          )                                                */
                                        /*                                                                                           */

                    BoIn(index_des_listes,NOIR,BLANC,PAS_COULEURS)
                         Bblock
                         EGAL(ITb1(fond,INDX(index_des_listes,NOIR)),FAUX);
                         EGAL(ITb1(bord,INDX(index_des_listes,NOIR)),VRAI);
                                        /* Reinitialisation des listes 'fond' et 'bord'.                                             */
                         Eblock
                    EBoI

                    BoIn(index_des_listes
                        ,MAX2(NOIR,SOUS(niveau_du_point_courant,largeur_de_bande))
                        ,MIN2(BLANC,ADD2(niveau_du_point_courant,largeur_de_bande))
                        ,I
                         )
                         Bblock
                         EGAL(ITb1(fond,INDX(index_des_listes,NOIR)),VRAI);
                         EGAL(ITb1(bord,INDX(index_des_listes,NOIR)),FAUX);
                                        /* On considere que "tout" est du "bord", sauf evidemment les points                         */
                                        /* qui ont le meme niveau que le point courant (a 'largeur_de_bande' pres),                  */
                                        /* et qui forment le "fond".                                                                 */
                         Eblock
                    EBoI

                    CALS(Iremplissage(zones_remplies
                                     ,imageA
                                     ,ADRESSE(point_de_depart)
                                     ,ADRESSE(coin_inferieur_gauche)
                                     ,ADRESSE(coin_superieur_droite)
                                     ,fond,bord
                                     ,est_______,nord______,ouest_____,sud_______
                                     ,nord_est__,nord_ouest,sud_ouest_,sud_est___
                                     ,niveau_du_point_courant
                                      )
                         );
                                        /* Marquage des points par lesquels on est passe...                                          */
                    Eblock
               ATes
                    Bblock
                    Eblock
               ETes
               Eblock
          ATes
               Bblock
               Eblock
          ETes
          Eblock
     end_image

     RETU_ERROR;
     Eblock

EFonctionI

_______________________________________________________________________________________________________________________________________
_______________________________________________________________________________________________________________________________________
/*===================================================================================================================================*/
/*************************************************************************************************************************************/
/*                                                                                                                                   */
/*        R E M P L I S S A G E   D U   V O I S I N A G E   D ' U N   P O I N T   D ' U N   A L B U M  :                             */
/*                                                                                                                                   */
/*************************************************************************************************************************************/

BFonctionI

DEFV(Common,DEFV(Float,SINT(Aremplissage_voisinage_____increment_recursif_du_niveau_de_remplissage,FZERO)));
                                        /* Cet increment (ou decrement, suivant son signe...) permet de changer le niveau de         */
                                        /* remplissage a chaque nouveau niveau de recursivite...                                     */

DEFV(Common,DEFV(Logical,SINT(Aremplissage_voisinage_____calculer_l_histogramme_du__bord,FAUX)));
                                        /* Cet indicateur permet de calculer l'histogramme du 'bord' en particulier pour savoir      */
                                        /* quel est son niveau majoritaire...                                                        */

DEFV(Common,DEFV(Int,SINT(Aremplissage_voisinage_____nombre_de_points_du__fond,ZERO)));
DEFV(Common,DEFV(pointF_3D,Aremplissage_voisinage_____centre_de_gravite_du__fond));

DEFV(Common,DEFV(Logical,SINT(Aremplissage_voisinage_____rechercher_le_niveau_maximal_d_un_point_isole,FAUX)));
DEFV(Common,DEFV(genere_Float,SINT(Aremplissage_voisinage_____niveau_maximal_d_un_point_isole,F_MOINS_L_INFINI)));
                                        /* Afin de calculer le niveau maximal du fond. On notera l'usage de 'genere_Float' et non    */
                                        /* pas de 'genere_p' afin de faciliter la recherche de ce maximum...                         */

#define   TEST_REMPLISSAGE_POINT_ISOLE(direction,x,y,z)                                                                                 \
                    Bblock                                                                                                              \
                    Test(IL_FAUT(direction))                                                                                            \
                         Bblock                                                                                                         \
                         Test(TEST_DANS_L_ALBUM(x,y,z))                                                                                 \
                              Bblock                                                                                                    \
                              DEFV(genere_p,INIT(voisin,Aload_point(albumA,x,y,z)));                                                    \
                                        /* Recuperation du niveau du point courant.                                                  */ \
                                                                                                                                        \
                              INCR(nombre_de_voisins_total,I);                                                                          \
                                                                                                                                        \
                              Test(EST_VRAI(ITb1(fond,INDX(voisin,NOIR))))                                                              \
                                   Bblock                                                                                               \
                                   INCR(nombre_de_voisins_appartenant_au_fond,I);                                                       \
                                   Eblock                                                                                               \
                              ATes                                                                                                      \
                                   Bblock                                                                                               \
                                   Eblock                                                                                               \
                              ETes                                                                                                      \
                              Eblock                                                                                                    \
                         ATes                                                                                                           \
                              Bblock                                                                                                    \
                              Eblock                                                                                                    \
                         ETes                                                                                                           \
                         Eblock                                                                                                         \
                    ATes                                                                                                                \
                         Bblock                                                                                                         \
                         Eblock                                                                                                         \
                    ETes                                                                                                                \
                    Eblock

#define   MOVE_REMPLISSAGE(direction,x,y,z)                                                                                             \
                    Bblock                                                                                                              \
                    Test(IL_FAUT(direction))                                                                                            \
                         Bblock                                                                                                         \
                         CALS(Aremplissage_voisinage(albumR                                                                             \
                                                    ,albumA                                                                             \
                                                    ,AlbumMarqueur                                                                      \
                                                    ,x,y,z                                                                              \
                                                    ,coin_gauche,coin_droite                                                            \
                                                    ,coin_inferieur,coin_superieur                                                      \
                                                    ,coin_avant,coin_arriere                                                            \
                                                    ,fond,bord                                                                          \
                                                    ,dc__6                                                                              \
                                                    ,dc__5                                                                              \
                                                    ,dc_4_                                                                              \
                                                    ,dc_46                                                                              \
                                                    ,dc_45                                                                              \
                                                    ,dc_2_                                                                              \
                                                    ,dc_26                                                                              \
                                                    ,dc_25                                                                              \
                                                    ,dc3__                                                                              \
                                                    ,dc3_6                                                                              \
                                                    ,dc3_5                                                                              \
                                                    ,dc34_                                                                              \
                                                    ,dc346                                                                              \
                                                    ,dc345                                                                              \
                                                    ,dc32_                                                                              \
                                                    ,dc326                                                                              \
                                                    ,dc325                                                                              \
                                                    ,dc1__                                                                              \
                                                    ,dc1_6                                                                              \
                                                    ,dc1_5                                                                              \
                                                    ,dc14_                                                                              \
                                                    ,dc146                                                                              \
                                                    ,dc145                                                                              \
                                                    ,dc12_                                                                              \
                                                    ,dc126                                                                              \
                                                    ,dc125                                                                              \
                                                    ,ADD2(niveau_de_remplissage                                                         \
                                                         ,Aremplissage_voisinage_____increment_recursif_du_niveau_de_remplissage        \
                                                          )                                                                             \
                                                     )                                                                                  \
                              );                                                                                                        \
                         Eblock                                                                                                         \
                    ATes                                                                                                                \
                         Bblock                                                                                                         \
                         Eblock                                                                                                         \
                    ETes                                                                                                                \
                    Eblock                                                                                                              \
                                        /* Fonction de test de la necessite de faire un deplacement dans                             */ \
                                        /* une 'direction' argument, et si oui, donc, remplir le voisinage                           */ \
                                        /* du point courant dans cette direction.                                                    */

DEFV(Local,DEFV(FonctionI,Aremplissage_voisinage(albumR
                                                ,albumA
                                                ,AlbumMarqueur
                                                ,X,Y,Z
                                                ,coin_gauche,coin_droite
                                                ,coin_inferieur,coin_superieur
                                                ,coin_avant,coin_arriere
                                                ,fond,bord
                                                ,dc__6
                                                ,dc__5
                                                ,dc_4_
                                                ,dc_46
                                                ,dc_45
                                                ,dc_2_
                                                ,dc_26
                                                ,dc_25
                                                ,dc3__
                                                ,dc3_6
                                                ,dc3_5
                                                ,dc34_
                                                ,dc346
                                                ,dc345
                                                ,dc32_
                                                ,dc326
                                                ,dc325
                                                ,dc1__
                                                ,dc1_6
                                                ,dc1_5
                                                ,dc14_
                                                ,dc146
                                                ,dc145
                                                ,dc12_
                                                ,dc126
                                                ,dc125
                                                ,niveau_de_remplissage
                                                 )
                )
     )
                                        /* Fonction introduite le 20231201121707...                                                  */
DEFV(Argument,DEFV(album,albumR));
                                        /* Album Resultat contenant le remplissage du contour Argument.                              */
DEFV(Argument,DEFV(album,albumA));
                                        /* Album Argument.                                                                           */
DEFV(Argument,DEFV(album,AlbumMarqueur));
                                        /* Album de marquage (introduit le 20231202121504)...                                        */
DEFV(Argument,DEFV(Int,X));
DEFV(Argument,DEFV(Int,Y));
DEFV(Argument,DEFV(Int,Z));
                                        /* Coordonnees entieres 'X', 'Y' et 'Z'.                                                     */
DEFV(Argument,DEFV(Int,coin_gauche));
DEFV(Argument,DEFV(Int,coin_droite));
DEFV(Argument,DEFV(Int,coin_inferieur));
DEFV(Argument,DEFV(Int,coin_superieur));
DEFV(Argument,DEFV(Int,coin_avant));
DEFV(Argument,DEFV(Int,coin_arriere));
                                        /* Definition du cadre a l'interieur duquel se fait le remplissage.                          */
DEFV(Argument,DEFV(Logical,DTb1(fond,COULEURS)));
                                        /* Definit ainsi pour chaque niveau s'il appartient ('VRAI') ou pas                          */
                                        /* ('FAUX') au fond, c'est-a-dire a ce que l'on doit remplir.                                */
DEFV(Argument,DEFV(Logical,DTb1(bord,COULEURS)));
                                        /* Definit ainsi pour chaque niveau s'il appartient ('VRAI') ou pas                          */
                                        /* ('FAUX') au bord, c'est-a-dire a ce qui delimite le contour.                              */
DEFV(Argument,DEFV(Logical,dc__6));
DEFV(Argument,DEFV(Logical,dc__5));
DEFV(Argument,DEFV(Logical,dc_4_));
DEFV(Argument,DEFV(Logical,dc_46));
DEFV(Argument,DEFV(Logical,dc_45));
DEFV(Argument,DEFV(Logical,dc_2_));
DEFV(Argument,DEFV(Logical,dc_26));
DEFV(Argument,DEFV(Logical,dc_25));
DEFV(Argument,DEFV(Logical,dc3__));
DEFV(Argument,DEFV(Logical,dc3_6));
DEFV(Argument,DEFV(Logical,dc3_5));
DEFV(Argument,DEFV(Logical,dc34_));
DEFV(Argument,DEFV(Logical,dc346));
DEFV(Argument,DEFV(Logical,dc345));
DEFV(Argument,DEFV(Logical,dc32_));
DEFV(Argument,DEFV(Logical,dc326));
DEFV(Argument,DEFV(Logical,dc325));
DEFV(Argument,DEFV(Logical,dc1__));
DEFV(Argument,DEFV(Logical,dc1_6));
DEFV(Argument,DEFV(Logical,dc1_5));
DEFV(Argument,DEFV(Logical,dc14_));
DEFV(Argument,DEFV(Logical,dc146));
DEFV(Argument,DEFV(Logical,dc145));
DEFV(Argument,DEFV(Logical,dc12_));
DEFV(Argument,DEFV(Logical,dc126));
DEFV(Argument,DEFV(Logical,dc125));
                                        /* Definition des Dimensions Cardinales a utiliser....                                       */
DEFV(Argument,DEFV(genere_Float,niveau_de_remplissage));
                                        /* Niveau a utiliser pour remplir le contour Argument.                                       */
/*-----------------------------------------------------------------------------------------------------------------------------------*/
     Bblock
     INIT_ERROR;
                                        /* ATTENTION : 'INIT_ERROR' est mis en tete des variables locales au cas ou des couples      */
                                        /* ('BDEFV','EDEFV') suivraient...                                                           */
     /*..............................................................................................................................*/
     Test(IFET(TEST_DANS_L_ALBUM(X,Y,Z)
              ,I3ET(INCLff(X,coin_gauche,coin_droite)
                   ,INCLff(Y,coin_inferieur,coin_superieur)
                   ,INCLff(Z,coin_avant,coin_arriere)
                    )
               )
          )
          Bblock
          Test(gTEST_POINT_ALBUM_NON_MARQUE(AlbumMarqueur,X,Y,Z))
               Bblock
                                        /* On ne traite que les points sur lesquels on n'est pas encore passe ; on                   */
                                        /* notera qu'il serait imprudent de tester 'NIVEAU_DE_MARQUAGE' avec                         */
                                        /* un 'IFEQ' a cause des problemes lies aux 'liste de substitution'.                         */
               DEFV(genere_p,INIT(point,Aload_point(albumA,X,Y,Z)));
                                        /* Recuperation du niveau du point courant.                                                  */

               Test(IL_FAUT(Aremplissage_voisinage_____rechercher_le_niveau_maximal_d_un_point_isole))
                    Bblock
                    Test(EST_FAUX(ITb1(fond,INDX(point,NOIR))))
                         Bblock
                         DEFV(Int,INIT(nombre_de_voisins_total,ZERO));
                         DEFV(Int,INIT(nombre_de_voisins_appartenant_au_fond,ZERO));

                         TEST_REMPLISSAGE_POINT_ISOLE(dc__6,NEUT(X),NEUT(Y),PREZ(Z));
                         TEST_REMPLISSAGE_POINT_ISOLE(dc__5,NEUT(X),NEUT(Y),SUCZ(Z));
                         TEST_REMPLISSAGE_POINT_ISOLE(dc_4_,NEUT(X),PREY(Y),NEUT(Z));
                         TEST_REMPLISSAGE_POINT_ISOLE(dc_46,NEUT(X),PREY(Y),PREZ(Z));
                         TEST_REMPLISSAGE_POINT_ISOLE(dc_45,NEUT(X),PREY(Y),SUCZ(Z));
                         TEST_REMPLISSAGE_POINT_ISOLE(dc_2_,NEUT(X),SUCY(Y),NEUT(Z));
                         TEST_REMPLISSAGE_POINT_ISOLE(dc_26,NEUT(X),SUCY(Y),PREZ(Z));
                         TEST_REMPLISSAGE_POINT_ISOLE(dc_25,NEUT(X),SUCY(Y),SUCZ(Z));
                         TEST_REMPLISSAGE_POINT_ISOLE(dc3__,PREX(X),NEUT(Y),NEUT(Z));
                         TEST_REMPLISSAGE_POINT_ISOLE(dc3_6,PREX(X),NEUT(Y),PREZ(Z));
                         TEST_REMPLISSAGE_POINT_ISOLE(dc3_5,PREX(X),NEUT(Y),SUCZ(Z));
                         TEST_REMPLISSAGE_POINT_ISOLE(dc34_,PREX(X),PREY(Y),NEUT(Z));
                         TEST_REMPLISSAGE_POINT_ISOLE(dc346,PREX(X),PREY(Y),PREZ(Z));
                         TEST_REMPLISSAGE_POINT_ISOLE(dc345,PREX(X),PREY(Y),SUCZ(Z));
                         TEST_REMPLISSAGE_POINT_ISOLE(dc32_,PREX(X),SUCY(Y),NEUT(Z));
                         TEST_REMPLISSAGE_POINT_ISOLE(dc326,PREX(X),SUCY(Y),PREZ(Z));
                         TEST_REMPLISSAGE_POINT_ISOLE(dc325,PREX(X),SUCY(Y),SUCZ(Z));
                         TEST_REMPLISSAGE_POINT_ISOLE(dc1__,SUCX(X),NEUT(Y),NEUT(Z));
                         TEST_REMPLISSAGE_POINT_ISOLE(dc1_6,SUCX(X),NEUT(Y),PREZ(Z));
                         TEST_REMPLISSAGE_POINT_ISOLE(dc1_5,SUCX(X),NEUT(Y),SUCZ(Z));
                         TEST_REMPLISSAGE_POINT_ISOLE(dc14_,SUCX(X),PREY(Y),NEUT(Z));
                         TEST_REMPLISSAGE_POINT_ISOLE(dc146,SUCX(X),PREY(Y),PREZ(Z));
                         TEST_REMPLISSAGE_POINT_ISOLE(dc145,SUCX(X),PREY(Y),SUCZ(Z));
                         TEST_REMPLISSAGE_POINT_ISOLE(dc12_,SUCX(X),SUCY(Y),NEUT(Z));
                         TEST_REMPLISSAGE_POINT_ISOLE(dc126,SUCX(X),SUCY(Y),PREZ(Z));
                         TEST_REMPLISSAGE_POINT_ISOLE(dc125,SUCX(X),SUCY(Y),SUCZ(Z));
                                        /* Ce qui precede a ete obtenu a l'aide du programme '$c' suivant :                          */
                                        /*                                                                                           */
                                        /*                                                                                           */
                                        /*   #include  <stdio.h>                                                                     */
                                        /*                                                                                           */
                                        /*   #define   X1(x)     (((x)>0) ? '1' : (((x)<0) ? '3' : '_'))                             */
                                        /*   #define   Y1(y)     (((y)>0) ? '2' : (((y)<0) ? '4' : '_'))                             */
                                        /*   #define   Z1(z)     (((z)>0) ? '5' : (((z)<0) ? '6' : '_'))                             */
                                        /*                                                                                           */
                                        /*   #define   X2(x)     (((x)>0) ? "SUCX(X)" : (((x)<0) ? "PREX(X)" : "NEUT(X)"))           */
                                        /*   #define   Y2(y)     (((y)>0) ? "SUCY(Y)" : (((y)<0) ? "PREY(Y)" : "NEUT(Y)"))           */
                                        /*   #define   Z2(z)     (((z)>0) ? "SUCZ(Z)" : (((z)<0) ? "PREZ(Z)" : "NEUT(Z)"))           */
                                        /*                                                                                           */
                                        /*   main()                                                                                  */
                                        /*             {                                                                             */
                                        /*             int       x,y,z;                                                              */
                                        /*                                                                                           */
                                        /*             for       (x=-1 ; x<=+1 ; x++)                                                */
                                        /*                       {                                                                   */
                                        /*                       for       (y=-1 ; y<=+1 ; y++)                                      */
                                        /*                                 {                                                         */
                                        /*                                 for       (z=-1 ; z<=+1 ; z++)                            */
                                        /*                                           {                                               */
                                        /*                                           if        ((x==0) && (y==0) & (z==0))           */
                                        /*                                                     {                                     */
                                        /*                                                     }                                     */
                                        /*                                           else                                            */
                                        /*                                                     {                                     */
                                        /*                                                     printf("procedure(");                 */
                                        /*                                                     printf("dc%c%c%c",X1(x),Y1(y),Z1(z)); */
                                        /*                                                     printf(",");                          */
                                        /*                                                     printf("%s,%s,%s",X2(x),Y2(y),Z2(z)); */
                                        /*                                                     printf(");\n");                       */
                                        /*                                                     }                                     */
                                        /*                                           }                                               */
                                        /*                                 }                                                         */
                                        /*                       }                                                                   */
                                        /*             }                                                                             */
                                        /*                                                                                           */
                                        /*                                                                                           */
                                        /* (voir 'v $xtc/DirectionsCardinales.01$c' a ce propos).                                    */

                         Test(IFEQ(nombre_de_voisins_appartenant_au_fond,nombre_de_voisins_total))
                                        /* Le point courant {X,Y} n'est pas du 'fond' et n'a pas de voisin, il est donc isole :      */
                              Bblock
                              EGAL(Aremplissage_voisinage_____niveau_maximal_d_un_point_isole
                                  ,MAX2(Aremplissage_voisinage_____niveau_maximal_d_un_point_isole,FLOT(point))
                                   );
                              Eblock
                         ATes
                              Bblock
                              Eblock
                         ETes
                         Eblock
                    ATes
                         Bblock
                         Eblock
                    ETes
                    Eblock
               ATes
                    Bblock
                    Eblock
               ETes

               Test(EST_FAUX(ITb1(bord,INDX(point,NOIR))))
                    Bblock
                    gMARQUAGE_POINT_ALBUM(AlbumMarqueur,X,Y,Z);
                                        /* Marquage systematique des points qui ne sont pas au bord dans une album                   */
                                        /* de travail, afin d'eviter des "trous" crees par exemple lorsque les                       */
                                        /* listes de "bord" et de "fond" ne sont pas complementaires.                                */
                    Test(EST_VRAI(ITb1(fond,INDX(point,NOIR))))
                         Bblock
                                        /* Traitement des points qui n'appartiennent pas au "bord", et                               */
                                        /* qui appartiennent au "fond".                                                              */
                         Astore_point(GENP(TRNP(niveau_de_remplissage)),albumR,X,Y,Z);
                                        /* Finalement, remplissage du point courant {X,Y} qui appartient au "fond",                  */
                                        /* n'appartient pas au "bord" et n'est pas masque (ou bien l'est, mais                       */
                                        /* est compatible avec le seuil et la portee du masquage...).                                */

                         INCR(Aremplissage_voisinage_____nombre_de_points_du__fond,I);
                                        /* Comptage des points.                                                                      */
                         INCR(ASD1(Aremplissage_voisinage_____centre_de_gravite_du__fond,x),FLOT(X));
                         INCR(ASD1(Aremplissage_voisinage_____centre_de_gravite_du__fond,y),FLOT(Y));
                         INCR(ASD1(Aremplissage_voisinage_____centre_de_gravite_du__fond,y),FLOT(Z));
                                        /* Calcul "iteratif" du centre de gravite.                                                   */
                         Eblock
                    ATes
                         Bblock
                         Eblock
                    ETes

                                        /* Puis, on passe aux voisins, suivant la regle de connexite demandee :                      */
                    MOVE_REMPLISSAGE(dc__6,NEUT(X),NEUT(Y),PREZ(Z));
                    MOVE_REMPLISSAGE(dc__5,NEUT(X),NEUT(Y),SUCZ(Z));
                    MOVE_REMPLISSAGE(dc_4_,NEUT(X),PREY(Y),NEUT(Z));
                    MOVE_REMPLISSAGE(dc_46,NEUT(X),PREY(Y),PREZ(Z));
                    MOVE_REMPLISSAGE(dc_45,NEUT(X),PREY(Y),SUCZ(Z));
                    MOVE_REMPLISSAGE(dc_2_,NEUT(X),SUCY(Y),NEUT(Z));
                    MOVE_REMPLISSAGE(dc_26,NEUT(X),SUCY(Y),PREZ(Z));
                    MOVE_REMPLISSAGE(dc_25,NEUT(X),SUCY(Y),SUCZ(Z));
                    MOVE_REMPLISSAGE(dc3__,PREX(X),NEUT(Y),NEUT(Z));
                    MOVE_REMPLISSAGE(dc3_6,PREX(X),NEUT(Y),PREZ(Z));
                    MOVE_REMPLISSAGE(dc3_5,PREX(X),NEUT(Y),SUCZ(Z));
                    MOVE_REMPLISSAGE(dc34_,PREX(X),PREY(Y),NEUT(Z));
                    MOVE_REMPLISSAGE(dc346,PREX(X),PREY(Y),PREZ(Z));
                    MOVE_REMPLISSAGE(dc345,PREX(X),PREY(Y),SUCZ(Z));
                    MOVE_REMPLISSAGE(dc32_,PREX(X),SUCY(Y),NEUT(Z));
                    MOVE_REMPLISSAGE(dc326,PREX(X),SUCY(Y),PREZ(Z));
                    MOVE_REMPLISSAGE(dc325,PREX(X),SUCY(Y),SUCZ(Z));
                    MOVE_REMPLISSAGE(dc1__,SUCX(X),NEUT(Y),NEUT(Z));
                    MOVE_REMPLISSAGE(dc1_6,SUCX(X),NEUT(Y),PREZ(Z));
                    MOVE_REMPLISSAGE(dc1_5,SUCX(X),NEUT(Y),SUCZ(Z));
                    MOVE_REMPLISSAGE(dc14_,SUCX(X),PREY(Y),NEUT(Z));
                    MOVE_REMPLISSAGE(dc146,SUCX(X),PREY(Y),PREZ(Z));
                    MOVE_REMPLISSAGE(dc145,SUCX(X),PREY(Y),SUCZ(Z));
                    MOVE_REMPLISSAGE(dc12_,SUCX(X),SUCY(Y),NEUT(Z));
                    MOVE_REMPLISSAGE(dc126,SUCX(X),SUCY(Y),PREZ(Z));
                    MOVE_REMPLISSAGE(dc125,SUCX(X),SUCY(Y),SUCZ(Z));
                    Eblock
               ATes
                    Bblock
                    Test(IL_FAUT(Aremplissage_voisinage_____calculer_l_histogramme_du__bord))
                         Bblock
                         INCR(ACCES_HISTOGRAMME(point),I);
                                        /* Le niveau 'point' fait partie du 'bord'...                                                */
                         Eblock
                    ATes
                         Bblock
                         Eblock
                    ETes
                    Eblock
               ETes
               Eblock
          ATes
               Bblock
               Eblock
          ETes
          Eblock
     ATes
          Bblock
          Eblock
     ETes

     RETU_ERROR;
     Eblock

#undef    MOVE_REMPLISSAGE
#undef    TEST_REMPLISSAGE_POINT_ISOLE

EFonctionI

/*===================================================================================================================================*/
/*************************************************************************************************************************************/
/*                                                                                                                                   */
/*        R E M P L I S S A G E   R E C U R S I F   D ' U N   C O N T O U R   D ' U N   A L B U M  :                                 */
/*                                                                                                                                   */
/*************************************************************************************************************************************/

BFonctionP

DEFV(Common,DEFV(Logical,SINT(Aremplissage_____editer_le_centre_de_gravite,FAUX)));
DEFV(Common,DEFV(Logical,SINT(Aremplissage_____calculer_l_histogramme_du__bord,FAUX)));

DEFV(Common,DEFV(FonctionP,POINTERp(Aremplissage(albumR
                                                ,albumA
                                                ,AlbumMarqueur
                                                ,ARGUMENT_POINTERs(point_de_depart)
                                                ,ARGUMENT_POINTERs(coin_inferieur_gauche_avant)
                                                ,ARGUMENT_POINTERs(coin_superieur_droite_arriere)
                                                ,fond,bord
                                                ,dc__6
                                                ,dc__5
                                                ,dc_4_
                                                ,dc_46
                                                ,dc_45
                                                ,dc_2_
                                                ,dc_26
                                                ,dc_25
                                                ,dc3__
                                                ,dc3_6
                                                ,dc3_5
                                                ,dc34_
                                                ,dc346
                                                ,dc345
                                                ,dc32_
                                                ,dc326
                                                ,dc325
                                                ,dc1__
                                                ,dc1_6
                                                ,dc1_5
                                                ,dc14_
                                                ,dc146
                                                ,dc145
                                                ,dc12_
                                                ,dc126
                                                ,dc125
                                                ,niveau_de_remplissage
                                                 )
                                    )
                 )
     )
                                        /* Fonction introduite le 20231201121707...                                                  */
DEFV(Argument,DEFV(album,albumR));
                                        /* Image Resultat contenant le remplissage du contour Argument.                              */
DEFV(Argument,DEFV(album,albumA));
                                        /* Image Argument.                                                                           */
DEFV(Argument,DEFV(album,AlbumMarqueur));
                                        /* Album de marquage (introduit le 20231202121504)...                                        */
DEFV(Argument,DEFV(pointF_3D,POINTERs(point_de_depart)));
                                        /* Coordonnees du point de depart de remplissage exprimees dans des                          */
                                        /* unites telles que l'unite vaut respectivement [Xmin,Xmax] et                              */
                                        /* [Ymin,Ymax].                                                                              */
DEFV(Argument,DEFV(pointF_3D,POINTERs(coin_inferieur_gauche_avant)));
                                        /* Le remplissage ne sera fait qu'a l'interieur d'un "cadre" que l'on                        */
                                        /* definit par son coin inferieur gauche,                                                    */
DEFV(Argument,DEFV(pointF_3D,POINTERs(coin_superieur_droite_arriere)));
                                        /* Definit par son coin superieur droit  ; ainsi, on pourra remplir                          */
                                        /* des contours ouverts dont le "cadre" proviendra du "cadre" defini                         */
                                        /* lors du trace des vecteurs 3D.                                                            */
DEFV(Argument,DEFV(Logical,DTb1(fond,COULEURS)));
                                        /* Definit ainsi pour chaque niveau s'il appartient ('VRAI') ou pas                          */
                                        /* ('FAUX') au fond, c'est-a-dire a ce que l'on doit remplir.                                */
DEFV(Argument,DEFV(Logical,DTb1(bord,COULEURS)));
                                        /* Definit ainsi pour chaque niveau s'il appartient ('VRAI') ou pas                          */
                                        /* ('FAUX') au bord, c'est-a-dire a ce qui delimite le contour.                              */
DEFV(Argument,DEFV(Logical,dc__6));
DEFV(Argument,DEFV(Logical,dc__5));
DEFV(Argument,DEFV(Logical,dc_4_));
DEFV(Argument,DEFV(Logical,dc_46));
DEFV(Argument,DEFV(Logical,dc_45));
DEFV(Argument,DEFV(Logical,dc_2_));
DEFV(Argument,DEFV(Logical,dc_26));
DEFV(Argument,DEFV(Logical,dc_25));
DEFV(Argument,DEFV(Logical,dc3__));
DEFV(Argument,DEFV(Logical,dc3_6));
DEFV(Argument,DEFV(Logical,dc3_5));
DEFV(Argument,DEFV(Logical,dc34_));
DEFV(Argument,DEFV(Logical,dc346));
DEFV(Argument,DEFV(Logical,dc345));
DEFV(Argument,DEFV(Logical,dc32_));
DEFV(Argument,DEFV(Logical,dc326));
DEFV(Argument,DEFV(Logical,dc325));
DEFV(Argument,DEFV(Logical,dc1__));
DEFV(Argument,DEFV(Logical,dc1_6));
DEFV(Argument,DEFV(Logical,dc1_5));
DEFV(Argument,DEFV(Logical,dc14_));
DEFV(Argument,DEFV(Logical,dc146));
DEFV(Argument,DEFV(Logical,dc145));
DEFV(Argument,DEFV(Logical,dc12_));
DEFV(Argument,DEFV(Logical,dc126));
DEFV(Argument,DEFV(Logical,dc125));
DEFV(Argument,DEFV(genere_p,niveau_de_remplissage));
                                        /* Niveau a utiliser pour remplir le contour Argument.                                       */
/*-----------------------------------------------------------------------------------------------------------------------------------*/
     Bblock
     DEFV(Int,INIT(X,UNDEF));
     DEFV(Int,INIT(Y,UNDEF));
     DEFV(Int,INIT(Z,UNDEF));
                                        /* Coordonnees entieres 'X', 'Y' et 'Z'.                                                     */
     /*..............................................................................................................................*/
     BoIn(niveau,NOIR,BLANC,PAS_COULEURS)
          Bblock
          Test(IFEQ(ITb1(bord,INDX(niveau,NOIR)),ITb1(fond,INDX(niveau,NOIR))))
               Bblock
               PRINT_ERREUR("un niveau ne peut appartenir a la fois au 'bord' et au 'fond'");
               CAL1(Prer1("ce niveau est %08X\n",niveau));
               Eblock
          ATes
               Bblock
               Eblock
          ETes
          Eblock
     EBoI

     Test(IL_FAUT(Aremplissage_____calculer_l_histogramme_du__bord))
          Bblock
          BoIn(niveau,NOIR,BLANC,PAS_COULEURS)
               Bblock
               CLIR(ACCES_HISTOGRAMME(niveau));
               Eblock
          EBoI
          Eblock
     ATes
          Bblock
          Eblock
     ETes

     EGAL(Aremplissage_voisinage_____niveau_maximal_d_un_point_isole,F_MOINS_L_INFINI);
                                        /* Afin de calculer le niveau maximal du fond, si besoin est.                                */

     BSaveModifyVariable(Logical
                        ,Aremplissage_voisinage_____calculer_l_histogramme_du__bord
                        ,Aremplissage_____calculer_l_histogramme_du__bord
                         );
                                        /* Pour des raisons d'imbrication, ce 'BSaveModifyVariable(...)' ne peut pas etre situe      */
                                        /* dans le 'Test(IL_FAUT(Aremplissage_____calculer_l_histogramme_du__bord))' precedent...    */

     CALS(dAinitialisation(AlbumMarqueur,NIVEAU_DE_NON_MARQUAGE));
                                        /* On verifie que le marquage est possible...                                                */
     EGAL(X,_cDENORMALISE_OX(ASI1(point_de_depart,x)));
     EGAL(Y,_cDENORMALISE_OY(ASI1(point_de_depart,y)));
     EGAL(Z,_cDENORMALISE_OZ(ASI1(point_de_depart,z)));
                                        /* Recuperation des coordonnees du point de depart, et mise dans                             */
                                        /* les coordonnees de l'album.                                                               */

     CLIR(Aremplissage_voisinage_____nombre_de_points_du__fond);
     CLIR(ASD1(Aremplissage_voisinage_____centre_de_gravite_du__fond,x));
     CLIR(ASD1(Aremplissage_voisinage_____centre_de_gravite_du__fond,y));
     CLIR(ASD1(Aremplissage_voisinage_____centre_de_gravite_du__fond,z));
                                        /* Initialisations diverses...                                                               */

     CALS(Aremplissage_voisinage(albumR
                                ,albumA
                                ,AlbumMarqueur
                                ,X,Y,Z
                                ,_cDENORMALISE_OX(ASI1(coin_inferieur_gauche_avant,x))
                                ,_cDENORMALISE_OX(ASI1(coin_superieur_droite_arriere,x))
                                ,_cDENORMALISE_OY(ASI1(coin_inferieur_gauche_avant,y))
                                ,_cDENORMALISE_OY(ASI1(coin_superieur_droite_arriere,y))
                                ,_cDENORMALISE_OZ(ASI1(coin_inferieur_gauche_avant,z))
                                ,_cDENORMALISE_OZ(ASI1(coin_superieur_droite_arriere,z))
                                ,fond,bord
                                ,dc__6
                                ,dc__5
                                ,dc_4_
                                ,dc_46
                                ,dc_45
                                ,dc_2_
                                ,dc_26
                                ,dc_25
                                ,dc3__
                                ,dc3_6
                                ,dc3_5
                                ,dc34_
                                ,dc346
                                ,dc345
                                ,dc32_
                                ,dc326
                                ,dc325
                                ,dc1__
                                ,dc1_6
                                ,dc1_5
                                ,dc14_
                                ,dc146
                                ,dc145
                                ,dc12_
                                ,dc126
                                ,dc125
                                ,CASP_Float(niveau_de_remplissage)
                                 )
          );
                                        /* Et remplissage recursif, voisinage par voisinage a partir                                 */
                                        /* du point de depart argument...                                                            */

     Test(IZNE(Aremplissage_voisinage_____nombre_de_points_du__fond))
          Bblock
          EGAL(ASD1(Aremplissage_voisinage_____centre_de_gravite_du__fond,x)
              ,DIVI(ASD1(Aremplissage_voisinage_____centre_de_gravite_du__fond,x)
                   ,FLOT(Aremplissage_voisinage_____nombre_de_points_du__fond)
                    )
               );
          EGAL(ASD1(Aremplissage_voisinage_____centre_de_gravite_du__fond,y)
              ,DIVI(ASD1(Aremplissage_voisinage_____centre_de_gravite_du__fond,y)
                   ,FLOT(Aremplissage_voisinage_____nombre_de_points_du__fond)
                    )
               );
          EGAL(ASD1(Aremplissage_voisinage_____centre_de_gravite_du__fond,z)
              ,DIVI(ASD1(Aremplissage_voisinage_____centre_de_gravite_du__fond,z)
                   ,FLOT(Aremplissage_voisinage_____nombre_de_points_du__fond)
                    )
               );
                                        /* Calcul "final" du centre de gravite.                                                      */

          Test(IL_FAUT(Aremplissage_____editer_le_centre_de_gravite))
               Bblock
               CAL3(Prme1("NombreDePoints=%d\n"
                         ,Aremplissage_voisinage_____nombre_de_points_du__fond
                          )
                    );
               CAL3(Prme3("XG=%+.^^^ YG=%+.^^^ ZG=%+.^^^\n"
                         ,ASD1(Aremplissage_voisinage_____centre_de_gravite_du__fond,x)
                         ,ASD1(Aremplissage_voisinage_____centre_de_gravite_du__fond,y)
                         ,ASD1(Aremplissage_voisinage_____centre_de_gravite_du__fond,z)
                          )
                    );
               Eblock
          ATes
               Bblock
               Eblock
          ETes
          Eblock
     ATes
          Bblock
          EGAL(ASD1(Aremplissage_voisinage_____centre_de_gravite_du__fond,x),FLOT(X));
          EGAL(ASD1(Aremplissage_voisinage_____centre_de_gravite_du__fond,y),FLOT(Y));
          EGAL(ASD1(Aremplissage_voisinage_____centre_de_gravite_du__fond,z),FLOT(Z));
                                        /* Dans ce cas, le centre de gravite (qui n'existe en fait pas) est le point de depart       */
                                        /* {X,Y}.                                                                                    */
          Eblock
     ETes

     ESaveModifyVariable(Logical
                        ,Aremplissage_voisinage_____calculer_l_histogramme_du__bord
                         );
                                        /* Pour des raisons d'imbrication, ce 'ESaveModifyVariable(...)' ne peut pas etre situe      */
                                        /* dans un 'Test(IL_FAUT(Aremplissage_____calculer_l_histogramme_du__bord))'...              */
     RETI(albumR);
     Eblock

EFonctionP

_______________________________________________________________________________________________________________________________________
_______________________________________________________________________________________________________________________________________
/*===================================================================================================================================*/
/*************************************************************************************************************************************/
/*                                                                                                                                   */
/*        E X T R A C T I O N   D ' U N   C O N T O U R   D ' U N E   I M A G E  :                                                   */
/*                                                                                                                                   */
/*************************************************************************************************************************************/

BFonctionP

#define   gALLER_A_GAUCHE                                                                                                               \
                    Bblock                                                                                                              \
                    SWAP(pas_horizontal,pas_vertical);                                                                                  \
                    EGAL(pas_horizontal,NEGA(pas_horizontal));                                                                          \
                    Eblock
#define   ALLER_A_GAUCHE                                                                                                                \
                    Bblock                                                                                                              \
                    Test(IL_NE_FAUT_PAS(inverser_les_conventions_DROITE_GAUCHE))                                                        \
                         Bblock                                                                                                         \
                         gALLER_A_GAUCHE;                                                                                               \
                         Eblock                                                                                                         \
                    ATes                                                                                                                \
                         Bblock                                                                                                         \
                         gALLER_A_DROITE;                                                                                               \
                         Eblock                                                                                                         \
                    ETes                                                                                                                \
                    Eblock
                                        /* Rotation de PI/2 du nombre complexe (pas_horizontal,pas_vertical).                        */
#define   gALLER_A_DROITE                                                                                                               \
                    Bblock                                                                                                              \
                    SWAP(pas_horizontal,pas_vertical);                                                                                  \
                    EGAL(pas_vertical,NEGA(pas_vertical));                                                                              \
                    Eblock
#define   ALLER_A_DROITE                                                                                                                \
                    Bblock                                                                                                              \
                    Test(IL_NE_FAUT_PAS(inverser_les_conventions_DROITE_GAUCHE))                                                        \
                         Bblock                                                                                                         \
                         gALLER_A_DROITE;                                                                                               \
                         Eblock                                                                                                         \
                    ATes                                                                                                                \
                         Bblock                                                                                                         \
                         gALLER_A_GAUCHE;                                                                                               \
                         Eblock                                                                                                         \
                    ETes                                                                                                                \
                    Eblock
                                        /* Rotation de 3xPI/2 du nombre complexe (pas_horizontal,pas_vertical).                      */

#define   DEPLACEMENT_POINT                                                                                                             \
                    Bblock                                                                                                              \
                    INCR(ASD1(point_courant,x),pas_horizontal);                                                                         \
                    INCR(ASD1(point_courant,y),pas_vertical);                                                                           \
                    Eblock                                                                                                              \
                                        /* Deplacement du point courant suivant (pas_horizontal,pas_vertical).                       */

#define   LE_POINT_VOISIN_EST_IL_A_L_INTERIEUR                                                                                          \
                    Bblock                                                                                                              \
                    Test(EST_VRAI(ITb1(interieur,INDX(load_point_valide(imageA,ASD1(point_courant,x),ASD1(point_courant,y)),NOIR))))    \
                         Bblock                                                                                                         \
                         EGAL(on_a_trouve_au_moins_un_voisin_a_l_interieur_du_contour,VRAI);                                            \
                                        /* Ainsi, on memorise que l'on a trouve au moins un voisin au point courant                  */ \
                                        /* qui soit a la fois a sa gauche, et a l'interieur du contour...                            */ \
                         Eblock                                                                                                         \
                    ATes                                                                                                                \
                         Bblock                                                                                                         \
                         Eblock                                                                                                         \
                    ETes                                                                                                                \
                    Eblock                                                                                                              \
                                        /* Le point courant est-il a l'interieur (procedure introduite le 20070214144219) ?          */

#define   SEND_CONTOUR(point)                                                                                                           \
                    Bblock                                                                                                              \
                    Test(IL_FAUT(emission_des_points))                                                                                  \
                         Bblock                                                                                                         \
                         Test(IFET(IFEQ(ASD1(point,x),COORDONNEE_CORRESPONDANT_A_UN_CONTOUR_VIDE)                                       \
                                  ,IFEQ(ASD1(point,y),COORDONNEE_CORRESPONDANT_A_UN_CONTOUR_VIDE)                                       \
                                   )                                                                                                    \
                              )                                                                                                         \
                                        /* Test introduit le 20051207143533...                                                       */ \
                              Bblock                                                                                                    \
                              SEND_F(INDIRECT(processus_recepteur),FLOT(ASD1(point,x)));                                                \
                              SEND_F(INDIRECT(processus_recepteur),FLOT(ASD1(point,y)));                                                \
                                        /* Cas d'un contour vide...                                                                  */ \
                              Eblock                                                                                                    \
                         ATes                                                                                                           \
                              Bblock                                                                                                    \
                              SEND_F(INDIRECT(processus_recepteur),_____cNORMALISE_OX(ASD1(point,x)));                                  \
                              SEND_F(INDIRECT(processus_recepteur),_____cNORMALISE_OY(ASD1(point,y)));                                  \
                                        /* Cas d'un contour non vide...                                                              */ \
                              Eblock                                                                                                    \
                         ETes                                                                                                           \
                                                                                                                                        \
                         SEND_L(INDIRECT(processus_recepteur),fin_de_contour);                                                          \
                                        /* Envoi du point...                                                                         */ \
                                                                                                                                        \
                         EGAL(un_point_au_moins_a_ete_emis,VRAI);                                                                       \
                                        /* Et ainsi, on sait qu'au moins un point a ete emis...                                      */ \
                         Eblock                                                                                                         \
                    ATes                                                                                                                \
                         Bblock                                                                                                         \
                         Eblock                                                                                                         \
                    ETes                                                                                                                \
                    Eblock                                                                                                              \
                                        /* Envoi, lorsque cela est demande, des coordonnee de 'point' a un processus recepteur.      */

DEFV(Common,DEFV(Logical,SINT(Iextraction_contour_____compatibilite_20070213,FAUX)));
                                        /* Indicateur introduit le 20070213135810 et permettant de controler la memorisation des     */
                                        /* points du contour. En effet, avant cette date, les points hors-images etaient marques     */
                                        /* sur la bordure de l'image ce qui etait la source d'artefacts ainsi que cela s'est vu      */
                                        /* dans 'v $xiirk/.DIFF.11.1.$U$INUTILE .xci.contours.11.X'. Il a donc etait de ne plus      */
                                        /* marquer, par defaut, les points hors-images...                                            */
DEFV(Common,DEFV(Positive,SINT(Iextraction_contour_____nombre_minimal_de_points_du_contour,UN)));
                                        /* Parametre introduit le 20070215125214 pour resoudre (provisoirement ?) le probleme des    */
                                        /* impasses ('v $xiii/contours$FON 20070214153034'). La valeur par defaut garantit la        */
                                        /* compatibilite anterieure. On pourra voir une application de cela, par exemple, dans le    */
                                        /* programme 'v $xiirk/.DIFF.11.2.$U nombre_minimal_de_points'...                            */
DEFV(Common,DEFV(Logical,SINT(Iextraction_contour_____compatibilite_20070407,FAUX)));
                                        /* Indicateur introduit le 20070407170648 et permettant d'eviter de se retrouver pieger      */
                                        /* a l'interieur d'un contour a trou ('v $xiii/contours$FON 20070407163803')...              */

DEFV(Common,DEFV(FonctionP,POINTERp(Iextraction_contour(imageR
                                                       ,imageA
                                                       ,ARGUMENT_POINTERs(point_de_depart)
                                                       ,exterieur,interieur
                                                       ,niveau_de_marquage_du_contour
                                                       ,emission_des_points
                                                       ,ARGUMENT_FACULTATIF(ARGUMENT_POINTERs(processus_recepteur))
                                                        )
                                    )
                 )
     )
DEFV(Argument,DEFV(image,imageR));
                                        /* Image Resultat contenant le contour extrait depuis l'image Argument.                      */
DEFV(Argument,DEFV(image,imageA));
                                        /* Image Argument.                                                                           */
DEFV(Argument,DEFV(pointF_2D,POINTERs(point_de_depart)));
                                        /* Coordonnees du point de depart d'extraction du contour exprimees                          */
                                        /* dans des unites telles que l'unite vaut respectivement [Xmin,Xmax] et                     */
                                        /* [Ymin,Ymax].                                                                              */
DEFV(Argument,DEFV(Logical,DTb1(exterieur,COULEURS)));
                                        /* Definit ainsi pour chaque niveau s'il appartient ('VRAI') ou pas                          */
                                        /* ('FAUX') a l'exterieur du contour a extraire.                                             */
DEFV(Argument,DEFV(Logical,DTb1(interieur,COULEURS)));
                                        /* Definit ainsi pour chaque niveau s'il appartient ('VRAI') ou pas                          */
                                        /* ('FAUX') a l'interieur du contour a extraire.                                             */
DEFV(Argument,DEFV(genere_p,niveau_de_marquage_du_contour));
                                        /* Niveau a utiliser pour remplir le contour Argument.                                       */
DEFV(Argument,DEFV(Logical,emission_des_points));
                                        /* Indique si les points extraits du contour doivent etre transmis ('VRAI')                  */
                                        /* ou pas ('FAUX') au 'processus_recepteur'.                                                 */
DEFV(Argument,DEFV(processus,POINTERs(processus_recepteur)));
                                        /* Description du processus auquel transmettre les coordonnees dans [0,1]                    */
                                        /* des points extraits du contour.                                                           */
/*-----------------------------------------------------------------------------------------------------------------------------------*/
     Bblock
     DEFV(Int,INIT(nombre_de_points,ZERO));
                                        /* Compteur des points traites sur une spirale ; on peut ainsi detecter                      */
                                        /* les cas ou il n'y a aucun contour a extraire...                                           */
     SPIRALE_DEFINITION
                                        /* Donnees de generation d'une spirale de parcours d'une image.                              */

     DEFV(pointI_2D,point_courant);
                                        /* Point courant lors de la recherche du vrai point de depart, puis lors                     */
                                        /* de l'extraction du contour. Il appartient a l'exterieur du contour.                       */
     DEFV(Logical,INIT(un_point_au_moins_a_ete_emis,FAUX));
                                        /* Cet indicateur logique a ete ajoute le 19990603092111 afin de detecter les cas ou alors   */
                                        /* qu'il faut emettre, rien ne l'a ete en fait (suite a une erreur...).                      */
     DEFV(Logical,INIT(fin_de_contour,LUNDEF));
                                        /* Cet indicateur logique permet de transmettre (eventuellement) s'il s'agit                 */
                                        /* du dernier point du contour ('VRAI') ou pas ('FAUX').                                     */
     /*..............................................................................................................................*/
     SPIRALE_VALIDATION;
                                        /* Validation des pas de parcours (pasX,pasY) des images.                                    */

     Test(IFNE(pasX,pasY))
          Bblock
          PRINT_ERREUR("'pasX' et 'pasY' doivent etre egaux afin de rechercher correctement les voisins");
          Eblock
     ATes
          Bblock
          Eblock
     ETes

     BoIn(niveau,NOIR,BLANC,PAS_COULEURS)
          Bblock
          Test(IFEQ(ITb1(interieur,INDX(niveau,NOIR)),ITb1(exterieur,INDX(niveau,NOIR))))
               Bblock
               PRINT_ERREUR("un niveau ne peut appartenir a la fois aux listes 'interieur' et 'exterieur'");
               CAL1(Prer1("ce niveau est %08X\n",niveau));
               Eblock
          ATes
               Bblock
               Eblock
          ETes
          Eblock
     EBoI

     Test(IL_FAUT(Iextraction_contour_____compatibilite_20070213))
          Bblock
          Test(IFOU(EST_VRAI(ITb1(interieur,INDX(Niveau____hors_image,NOIR)))
                   ,EST_FAUX(ITb1(exterieur,INDX(Niveau____hors_image,NOIR)))
                    )
               )
               Bblock
               PRINT_ERREUR("le 'Niveau____hors_image' doit faire partie de l'exterieur du contour");
               Eblock
          ATes
               Bblock
               Eblock
          ETes
          Eblock
     ATes
          Bblock
          Eblock
     ETes

     INITIALISATION_POINT_2D(point_courant
                            ,_cDENORMALISE_OX(ASI1(point_de_depart,x))
                            ,_cDENORMALISE_OY(ASI1(point_de_depart,y))
                             );
                                        /* Recuperation des coordonnees du point courant, et mise dans les                           */
                                        /* coordonnees de l'image pour la recherche du vrai point de depart.                         */

     Test(TEST_HORS_IMAGE(ASD1(point_courant,x),ASD1(point_courant,y)))
          Bblock
          PRINT_ERREUR("le point de depart est hors de l'image");
          CAL1(Prer2("(le point de depart est {%d,%d})\n"
                    ,ASD1(point_courant,x)
                    ,ASD1(point_courant,y)
                     )
               );
                                        /* Introduit le 20190321122059 lors de la mise au point de 'v $xrc/julia.82$K E_DEPART_'...  */
          Eblock
     ATes
          Bblock
          Test(EST_VRAI(ITb1(interieur,INDX(load_point_valide(imageA,ASD1(point_courant,x),ASD1(point_courant,y)),NOIR))))
               Bblock
               PRINT_ERREUR("le point de depart est a l'interieur du contour");
               CAL1(Prer2("(le point de depart est {%d,%d})\n"
                         ,ASD1(point_courant,x)
                         ,ASD1(point_courant,y)
                          )
                    );
               Eblock
          ATes
               Bblock
               begin_image
                    Bblock
                    Test(EST_VRAI(ITb1(interieur,INDX(load_point(imageA,X,Y),NOIR))))
                         Bblock
                         INCR(nombre_de_points,I);
                                        /* Comptage des points susceptibles d'etre a l'interieur du contour a extraire.              */
                         Eblock
                    ATes
                         Bblock
                         Eblock
                    ETes
                    Eblock
               end_image

               Test(IZEQ(nombre_de_points))
                    Bblock
                    PRINT_ERREUR("il n'y a pas de contour repondant aux specifications");

                    INITIALISATION_POINT_2D(point_courant
                                           ,COORDONNEE_CORRESPONDANT_A_UN_CONTOUR_VIDE
                                           ,COORDONNEE_CORRESPONDANT_A_UN_CONTOUR_VIDE
                                            );
                                        /* Ces coordonnees particulieres ont ete introduites le 20051207143533 pour pouvoir tester   */
                                        /* ce cas au retour ('v $xci/contours.11$K COORDONNEE_CORRESPONDANT_A_UN_CONTOUR_VIDE').     */
                    Eblock
               ATes
                    Bblock
                    DEFV(Logical,INIT(premier_tour,LUNDEF));
                                        /* Cet indicateur logique permet d'effectuer au moins une fois la boucle                     */
                                        /* d'extraction de contour.                                                                  */

                    DEFV(pointI_2D,vrai_point_de_depart);
                                        /* Coordonnees du vrai point de depart d'extraction du contour exprimees                     */
                                        /* dans [Xmin,Xmax][Ymin,Ymax].                                                              */
                    DEFV(pointI_2D,dernier_point_exterieur);
                                        /* Coordonnees du dernier point exterieur rencontre exprimees                                */
                                        /* dans [Xmin,Xmax][Ymin,Ymax] (introduit le 20070407170648...).                             */

                    DEFV(Logical,INIT(inverser_les_conventions_DROITE_GAUCHE,FAUX));
                                        /* Introduit le 20070214153034 afin de faire des tests lies a un probleme de contours qui    */
                                        /* ne sont pas extraits car quasiment immediatement le point courant repasse par le point    */
                                        /* de depart. Cette situation se rencontre quand le point de depart est en quelques sorte    */
                                        /* a l'interieur ou a l'entree d'une impasse ; en effet, pour ressortir d'une impasse, il    */
                                        /* faut necessairement repasser par l'entree...                                              */
                    DEFV(Int,INIT(pas_horizontal,CHOI(pasX,pasY)));
                    DEFV(Int,INIT(pas_vertical,ZERO));
                                        /* Pas horizontaux et verticaux de recherche ; on va partir horizontalement vers la droite.  */
                    DEFV(Int,INIT(EnTete_de_sauvegardM ## pas_horizontal,UNDEF));
                    DEFV(Int,INIT(EnTete_de_sauvegardM ## pas_vertical,UNDEF));
                                        /* Sauvegarde des pas horizontaux et verticaux lors de l'examen des trois                    */
                                        /* voisins de gauche.                                                                        */
                    DEFV(Int,INIT(EnTete_de_sauvegardM ## pas_horizontal_initial,UNDEF));
                    DEFV(Int,INIT(EnTete_de_sauvegardM ## pas_vertical_initial,UNDEF));
                                        /* Sauvegarde des pas horizontaux et verticaux a l'instant initial. On notera qu'a la fin    */
                                        /* du parcours d'un contour,{pas_horizontal,pas_vertical} ne se retrouvent pas a l'etat      */
                                        /* initiale {SavM_____pas_horizontal_initial,SavM_____pas_vertical_initial} ainsi qu'on      */
                                        /* pourrait le croire naivement...                                                           */

                    DEFV(Positive,INIT(nombre_de_points_du_contour,ZERO));
                                        /* Introduit le 20070215125214...                                                            */

                    Tant(IFOU(TEST_HORS_IMAGE(ASD1(point_courant,x),ASD1(point_courant,y))
                             ,EST_VRAI(ITb1(exterieur
                                           ,INDX(load_point_valide(imageA,ASD1(point_courant,x),ASD1(point_courant,y)),NOIR)
                                            )
                                       )
                              )
                         )
                         Bblock
                                        /* Ainsi, on cherche "en spirale" le premier point interieur au                              */
                                        /* contour et qui existe (DANS_L_IMAGE).                                                     */
                         TRANSFERT_POINT_2D(dernier_point_exterieur,point_courant);
                                        /* A priori, on memorise le point exterieur courant, qui a la fin sera le dernier...         */

                         SPIRALE_INITIALISATION;
                                        /* Initialisation dynamique de 'spirale_nombre_de_points_a_traiter'.                         */
                         SPIRALE_DEPLACEMENT(ASD1(point_courant,x),ASD1(point_courant,y));
                                        /* Deplacement du point courant de la spirale...                                             */
                                        /* ATTENTION : on n'utilise pas 'SPIRALE_DEPLACEMENT_ET_PARCOURS(...)' afin de garantir la   */
                                        /* terminaison du processus 'Tant(...)'.                                                     */
                         SPIRALE_PARCOURS;
                                        /* Parcours de la spirale avec rotation eventuelle de PI/2 du bras courant...                */
                         Eblock
                    ETan

                    SPIRALE_REINITIALISATION_BRAS;
                                        /* Reinitialisation de la spirale en son centre, sans reinitialiser la direction             */
                                        /* et le sens du bras courant...                                                             */
                                        /* On notera, que (spirale_delta_horizontal,spirale_delta_vertical) n'est pas                */
                                        /* reinitialise afin de continuer dans la meme direction...                                  */

                    Test(IL_FAUT(Iextraction_contour_____compatibilite_20070407))
                         Bblock
                         Tant(IFOU(TEST_HORS_IMAGE(ASD1(point_courant,x),ASD1(point_courant,y))
                                  ,EST_VRAI(ITb1(interieur
                                                ,INDX(load_point_valide(imageA,ASD1(point_courant,x),ASD1(point_courant,y)),NOIR)
                                                 )
                                            )
                                   )
                              )
                              Bblock
                                        /* Ainsi, on cherche "en spirale" le premier point exterieur au                              */
                                        /* contour et qui existe (DANS_L_IMAGE) a partir du premier point                            */
                                        /* interieur trouve dans la boucle 'Tant' precedente.                                        */
                              SPIRALE_INITIALISATION;
                                        /* Initialisation dynamique de 'spirale_nombre_de_points_a_traiter'.                         */
                              SPIRALE_DEPLACEMENT(ASD1(point_courant,x),ASD1(point_courant,y));
                                        /* Deplacement du point courant de la spirale...                                             */
                                        /* ATTENTION : on n'utilise pas 'SPIRALE_DEPLACEMENT_ET_PARCOURS(...)' afin de garantir la   */
                                        /* terminaison du processus 'Tant(...)'.                                                     */
                              SPIRALE_PARCOURS;
                                        /* Parcours de la spirale avec rotation eventuelle de PI/2 du bras courant...                */
                              Eblock
                         ETan
                         Eblock
                    ATes
                         Bblock
                         TRANSFERT_POINT_2D(point_courant,dernier_point_exterieur);
                                        /* Repositionnement sur le dernier point exterieur (introduit le 20070407170648)...          */
                         Eblock
                    ETes

                    TRANSFERT_POINT_2D(vrai_point_de_depart,point_courant);
                                        /* Recuperation des coordonnees du point de depart en tant que dernier                       */
                                        /* point de l'exterieur rencontre avant un point de l'interieur du                           */
                                        /* contour a extraire (ces deux points devant etre dans l'image...).                         */

                    EGAL(premier_tour,VRAI);
                                        /* Afin de faire au moins la sequence d'extraction une fois...                               */
                    EGAL(fin_de_contour,FAUX);
                                        /* On n'en n'est pas encore la...                                                            */

                    EGAL(EnTete_de_sauvegardM ## pas_horizontal_initial,pas_horizontal);
                    EGAL(EnTete_de_sauvegardM ## pas_vertical_initial,pas_vertical);
                                        /* Sauvegarde de l'etat initial de l'orientation des deplacements (ceci fut introduit        */
                                        /* le 20070214173007...).                                                                    */

                    Tant(I3OU(EST_VRAI(premier_tour)
                             ,IFOU(IFNE(ASD1(vrai_point_de_depart,x),ASD1(point_courant,x))
                                  ,IFNE(ASD1(vrai_point_de_depart,y),ASD1(point_courant,y))
                                   )
                             ,I3ET(IFET(IFEQ(ASD1(vrai_point_de_depart,x),ASD1(point_courant,x))
                                       ,IFEQ(ASD1(vrai_point_de_depart,y),ASD1(point_courant,y))
                                        )
                                  ,IFOU(IFNE(pas_horizontal,EnTete_de_sauvegardM ## pas_horizontal_initial)
                                       ,IFNE(pas_vertical,EnTete_de_sauvegardM ## pas_vertical_initial)
                                        )
                                  ,IFLT(nombre_de_points_du_contour,Iextraction_contour_____nombre_minimal_de_points_du_contour)
                                   )
                                        /* Cette condition a ete introduite le 20070215125214 pour resoudre (provisoirement ?)       */
                                        /* le probleme des impasses ('v $xiii/contours$FON 20070214153034'). Ainsi, si l'on est      */
                                        /* de retour au point de depart sans etre dans la meme direction qu'initialement (en effet   */
                                        /* dans le cas contraire, on referait exactement la meme extraction) et si le contour est    */
                                        /* trop petit (critere arbitraire...), on poursuit l'extraction. Cette situation d'impasse   */
                                        /* se rencontre, par exemple, ainsi :                                                        */
                                        /*                                                                                           */
                                        /*                                                                                           */
                                        /*                   |    |    |    |                                                        */
                                        /*                  -+----+----+----+-                                                       */
                                        /*                   |////|////|////|                                                        */
                                        /*                   |////|////|////|                                                        */
                                        /*                   |////|////|////|                                                        */
                                        /*                  -+----+----+----+-                                                       */
                                        /*                   |////|    |////|                                                        */
                                        /*                   |////| /\ |////|                                                        */
                                        /*                   |////| || |////|                                                        */
                                        /*                  -+----+-||-+----+-                                                       */
                                        /*                   |    |    |////|                                                        */
                                        /*                   |    | De |////|                                                        */
                                        /*                   |    |    |////|                                                        */
                                        /*                  -+----+----+----+-                                                       */
                                        /*                   |    |    |    |                                                        */
                                        /*                                                                                           */
                                        /*                                                                                           */
                                        /* La case marquee 'De' correspond au point de depart d'extraction du contour. L'exploration */
                                        /* monte et penetre dans l'impasse superieure. La seule facon d'en sortir est de parcourir   */
                                        /* le chemin aller a l'envers. Alors on repasse necessairement par la case 'De'...           */
                              )
                         )
                         Bblock
                         DEFV(pointI_2D,save1_point_courant);
                                        /* Sauvegarde du point courant lors de l'extraction du contour. Il appartient a l'exterieur  */
                                        /* du contour.                                                                               */
                         DEFV(Logical,INIT(on_a_trouve_au_moins_un_voisin_a_l_interieur_du_contour,LUNDEF));
                                        /* Indicateur montrant si au moins un voisin a gauche a ete rencontre.                       */

                         Test(IFOU(TEST_DANS_L_IMAGE(ASD1(point_courant,x),ASD1(point_courant,y))
                                  ,IFET(TEST_HORS_IMAGE(ASD1(point_courant,x),ASD1(point_courant,y))
                                       ,IL_FAUT(Iextraction_contour_____compatibilite_20070213)
                                        )
                                   )
                              )
                              Bblock
                              SEND_CONTOUR(point_courant);
                                        /* Lorsque cela est demande, on transmet les coordonnees {x,y} du point                      */
                                        /* courant (et du point de depart la premiere fois) du contour.                              */
                              Eblock
                         ATes
                              Bblock
                              Eblock
                         ETes

                         EGAL(on_a_trouve_au_moins_un_voisin_a_l_interieur_du_contour,FAUX);
                                        /* A priori, on n'a pas encore trouve de voisin a gauche du point courant...                 */

                         TRANSFERT_POINT_2D(save1_point_courant,point_courant);
                                        /* Sauvegarde du point courant au debut de la recherche des voisins.                         */

                         ALLER_A_GAUCHE;
                         DEPLACEMENT_POINT;
                                        /* Et on tourne a gauche initialement.                                                       */

                         Tant(EST_FAUX(on_a_trouve_au_moins_un_voisin_a_l_interieur_du_contour))
                              Bblock
                              DEFV(pointI_2D,save2_point_courant);
                                        /* Sauvegarde du point courant lors de l'examen des trois voisins de gauche. Il appartient   */
                                        /* a l'exterieur du contour.                                                                 */
                              DEFV(Int,INIT(compteur_des_voisins,ZERO));
                                        /* Compteur des voisins destines a verifier qu'il y en a trois au plus...                    */
                              DEFV(Logical,INIT(chercher_un_point_courant_a_l_exterieur_du_contour,VRAI));
                                        /* Indicateur controlant la recherche d'un point courant a l'exterieur du contour...         */

                              Tant(IL_FAUT(chercher_un_point_courant_a_l_exterieur_du_contour))
                                   Bblock
                                   Test(TEST_DANS_L_IMAGE(ASD1(point_courant,x),ASD1(point_courant,y)))
                                        Bblock
                                        Test(EST_VRAI(ITb1(interieur
                                                          ,INDX(load_point(imageA,ASD1(point_courant,x),ASD1(point_courant,y)),NOIR)
                                                           )
                                                      )
                                             )
                                             Bblock
                                        /* Cas d'un point dans l'image et a l'interieur du contour : on continue la recherche...     */
                                             INCR(compteur_des_voisins,I);
                                        /* Comptage des voisins...                                                                   */
                                             Eblock
                                        ATes
                                             Bblock
                                             EGAL(chercher_un_point_courant_a_l_exterieur_du_contour,FAUX);
                                        /* Cas d'un point dans l'image et a l'exterieur du contour : on a trouve le point...         */
                                             Eblock
                                        ETes
                                        Eblock
                                   ATes
                                        Bblock
                                        /* Cas d'un point hors de l'image :                                                          */
                                        Test(EST_VRAI(ITb1(interieur,INDX(Niveau____hors_image,NOIR))))
                                             Bblock
                                        /* Cas d'un point hors de l'image, considere comme etant a l'interieur du contour : on       */
                                        /* continue la recherche...                                                                  */
                                             INCR(compteur_des_voisins,I);
                                        /* Comptage des voisins...                                                                   */
                                             Eblock
                                        ATes
                                             Bblock
                                             EGAL(chercher_un_point_courant_a_l_exterieur_du_contour,FAUX);
                                        /* Cas d'un point hors de l'image, considere comme etant a l'exterieur du contour : on a     */
                                        /* trouve le point...                                                                        */
                                             Eblock
                                        ETes
                                        Eblock
                                   ETes

                                   Test(IL_FAUT(chercher_un_point_courant_a_l_exterieur_du_contour))
                                        Bblock
                                        Test(IFGT(compteur_des_voisins,TROIS))
                                        /* Ce test a ete introduit le 20070406222210 dans le but de resoudre le cas suivant :        */
                                        /*                                                                                           */
                                        /*                                                                                           */
                                        /*                   |    |    |    |                                                        */
                                        /*                  -+----+----+----+-                                                       */
                                        /*                   |    |////|    |                                                        */
                                        /*                   |    |////|    |                                                        */
                                        /*                   |    |////|    |                                                        */
                                        /*                  -+----+----+----+-                                                       */
                                        /*                   |////|    |////|                                                        */
                                        /*                   |////| PC |////|                                                        */
                                        /*                   |////|    |////|                                                        */
                                        /*                  -+----+----+----+-                                                       */
                                        /*                   |    |////|    |                                                        */
                                        /*                   |    |////|    |                                                        */
                                        /*                   |    |////|    |                                                        */
                                        /*                  -+----+----+----+-                                                       */
                                        /*                   |    |    |    |                                                        */
                                        /*                                                                                           */
                                        /*                                                                                           */
                                        /* (ou 'PC' designe 'save1_point_courant' qui est le point courant de l'exterieur ; les      */
                                        /* cases vides appartiennent a l'EXTERIEUR et les cases hachurees a l'INTERIEUR) qui a       */
                                        /* cette date conduit a un bouclage infini du 'Tant(...)' dans lequel nous sommes ici...     */
                                        /*                                                                                           */
                                        /* En fait, le 20070407163803, je comprends que le probleme vient du fait que cette fonction */
                                        /* 'Iextraction_contour(...)' fait l'hypothese implicite que le contour est plein. Or dans   */
                                        /* l'exemple ci-dessus, il contient des trous (en fait un seul, celui qui est marque 'PC').  */
                                        /* L'extracteur de contour se retrouve piege a l'interieur, alors qu'il se croit situe a     */
                                        /* l'exterieur. Le scenario est le suivant :                                                 */
                                        /*                                                                                           */
                                        /*                                                                                           */
                                        /*                   |    |    |    |                                                        */
                                        /*                  -+----+----+----+-                                                       */
                                        /*                   |    |////|    |                                                        */
                                        /*                   |    |////|    |                                                        */
                                        /*                   |    |////|    |                                                        */
                                        /*                  -+----+----+----+-                                                       */
                                        /*                   |////|    |////|                                                        */
                                        /*                   |////| De |////|             arret de la seconde boucle 'Tant(...)'     */
                                        /*                   |////|    |////|                                                        */
                                        /*                  -+----+----+----+-                                                       */
                                        /*                   |    |//\/|    |                                                        */
                                        /*                   |    |/IN/|    |             arret de la premiere boucle 'Tant(...)'    */
                                        /*                   |    |////|    |                                                        */
                                        /*                  -+----+----+----+-                                                       */
                                        /*                   |    | /\ |    |                                                        */
                                        /*                   |    | EX |    |                                                        */
                                        /*                   |    |    |    |                                                        */
                                        /*                  -+----+----+----+-                                                       */
                                        /*                   |    | /\ |    |                                                        */
                                        /*                   |    | EX |    |                                                        */
                                        /*                   |    |    |    |                                                        */
                                        /*                  -+----+----+----+-                                                       */
                                        /*                   |    |    |    |                                                        */
                                        /*                                                                                           */
                                        /*                                                                                           */
                                        /* La boucle 'Tant(...)' qui recherche "le premier point interieur au contour" ci-dessus     */
                                        /* a parcouru les points exterieurs marques 'EX' et s'est arretee sur le premier point       */
                                        /* marque 'IN'. Ensuite, la boucle 'Tant(...)' qui recherche "le premier point exterieur au  */
                                        /* contour" a parcouru les points interieurs marques 'IN' (en fait un seul) et s'est arretee */
                                        /* sur le premier point exterieur marque 'De'. Ce dernier est donc le point de depart qui    */
                                        /* est malheureusement piege a l'interieur...                                                */
                                        /*                                                                                           */
                                        /* Le 20070407170648, grace a 'Iextraction_contour_____compatibilite_20070407' ce probleme   */
                                        /* fut resolu. La solution a consiste a supprimer, par defaut, la seconde boucle 'Tant(...)' */
                                        /* et en revenant donc sur le dernier point marque 'EX' de la premiere boucle 'Tant(...)',   */
                                        /* qui devient donc le point de depart 'De' :                                                */
                                        /*                                                                                           */
                                        /*                                                                                           */
                                        /*                   |    |    |    |                                                        */
                                        /*                  -+----+----+----+-                                                       */
                                        /*                   |    |////|    |                                                        */
                                        /*                   |    |////|    |                                                        */
                                        /*                   |    |////|    |                                                        */
                                        /*                  -+----+----+----+-                                                       */
                                        /*                   |////|    |////|                                                        */
                                        /*                   |////|    |////|                                                        */
                                        /*                   |////|    |////|                                                        */
                                        /*                  -+----+----+----+-                                                       */
                                        /*                   |    |//\/|    |                                                        */
                                        /*                   |    |/IN/|    |             arret de la premiere boucle 'Tant(...)'    */
                                        /*                   |    |////|    |                                                        */
                                        /*                  -+----+----+----+-                                                       */
                                        /*                   |    | /\ |    |                                                        */
                                        /*                   |    | De |    |                                                        */
                                        /*                   |    |    |    |                                                        */
                                        /*                  -+----+----+----+-                                                       */
                                        /*                   |    | /\ |    |                                                        */
                                        /*                   |    | EX |    |                                                        */
                                        /*                   |    |    |    |                                                        */
                                        /*                  -+----+----+----+-                                                       */
                                        /*                   |    |    |    |                                                        */
                                        /*                                                                                           */
                                        /*                                                                                           */
                                        /* et le trou a l'interieur du contour est donc evite puisque l'on n'y penetre pas ...       */
                                             Bblock
                                             PRINT_ERREUR("trop de voisins a l'interieur ont ete trouve pour le point exterieur");
                                             CAL1(Prer2("(le point exterieur est {%d,%d})\n"
                                                       ,ASD1(save1_point_courant,x)
                                                       ,ASD1(save1_point_courant,y)
                                                        )
                                                  );
                                             Eblock
                                        ATes
                                             Bblock
                                             Eblock
                                        ETes

                                        TRANSFERT_POINT_2D(point_courant,save1_point_courant);
                                        /* On retourne sur le point courant de debut de la recherche courante,                       */

                                        ALLER_A_DROITE;
                                        DEPLACEMENT_POINT;
                                        /* Et on tourne a droite.                                                                    */
                                        Eblock
                                   ATes
                                        Bblock
                                        Eblock
                                   ETes
                                   Eblock
                              ETan

                              TRANSFERT_POINT_2D(save2_point_courant,point_courant);
                              EGAL(EnTete_de_sauvegardM ## pas_horizontal,pas_horizontal);
                              EGAL(EnTete_de_sauvegardM ## pas_vertical,pas_vertical);
                                        /* Sauvegardes du point courant et de la direction courante de                               */
                                        /* deplacement avant de regarder les trois voisins de gauche (c'est-a-dire                   */
                                        /* celui qui est en arriere-gauche, celui qui est a gauche et enfin celui                    */
                                        /* qui est en avant-gauche.                                                                  */

                              ALLER_A_GAUCHE;
                              DEPLACEMENT_POINT;
                                        /* Test du voisin de gauche :                                                                */

                              LE_POINT_VOISIN_EST_IL_A_L_INTERIEUR;
                                        /* Est-il interieur ?                                                                        */

                              ALLER_A_GAUCHE;
                              DEPLACEMENT_POINT;
                                        /* Test du voisin d'arriere-gauche :                                                         */

                              LE_POINT_VOISIN_EST_IL_A_L_INTERIEUR;
                                        /* Est-il interieur ?                                                                        */

                              ALLER_A_GAUCHE;
                              ALLER_A_GAUCHE;
                              DEPLACEMENT_POINT;
                              DEPLACEMENT_POINT;
                                        /* Test du voisin d'avant-gauche :                                                           */

                              LE_POINT_VOISIN_EST_IL_A_L_INTERIEUR;
                                        /* Est-il interieur ?                                                                        */

                              TRANSFERT_POINT_2D(point_courant,save2_point_courant);
                              EGAL(pas_horizontal,EnTete_de_sauvegardM ## pas_horizontal);
                              EGAL(pas_vertical,EnTete_de_sauvegardM ## pas_vertical);
                                        /* Et les conditions initiales sont restaurees : le point courant et la direction            */
                                        /* courante de deplacement.                                                                  */
                                        /*                                                                                           */
                                        /* Le 20070214150322 je note que cette restauration semble inutile car, en effet, ayant      */
                                        /* effectue quatre fois {ALLER_A_GAUCHE;DEPLACEMENT_POINT}, on a finalement tourne de        */
                                        /* quatre fois pi/2 et on est donc retombe sur nos pas. Malgre tout, dans le doute, je       */
                                        /* m'abstiens de la supprimer...                                                             */

                              Test(EST_FAUX(on_a_trouve_au_moins_un_voisin_a_l_interieur_du_contour))
                                   Bblock
                                   TRANSFERT_POINT_2D(point_courant,save1_point_courant);
                                        /* Lorsqu'aucun voisin a gauche n'a ete trouve, on retourne sur                              */
                                        /* le point courant de debut de la recherche courante.                                       */

                                   ALLER_A_DROITE;
                                   DEPLACEMENT_POINT;
                                        /* Et on tourne a droite.                                                                    */
                                   Eblock
                              ATes
                                   Bblock
                                   Eblock
                              ETes
                              Eblock
                         ETan

                         INCR(nombre_de_points_du_contour,I);
                                        /* Comptage des points du contour introduit le 20070215125214...                             */

                         Test(IL_NE_FAUT_PAS(Iextraction_contour_____compatibilite_20070213))
                              Bblock
                              store_point_valide(niveau_de_marquage_du_contour
                                                ,imageR
                                                ,ASD1(point_courant,x)
                                                ,ASD1(point_courant,y)
                                                ,FVARIABLE
                                                 );
                                        /* Et on ne marque que les points du contour qui sont dans l'image...                        */
                              Eblock
                         ATes
                              Bblock
                              store_point(niveau_de_marquage_du_contour
                                         ,imageR
                                         ,TRON(ASD1(point_courant,x),Xmin,Xmax)
                                         ,TRON(ASD1(point_courant,y),Ymin,Ymax)
                                         ,FVARIABLE
                                          );
                                        /* Et on marque le contour de facon que les points hors-ecran apparaissent                   */
                                        /* marques sur la bordure de l'image...                                                      */
                              Eblock
                         ETes

                         EGAL(premier_tour,FAUX);
                                        /* Ainsi, on sait que l'on a effectue la boucle au moins une fois...                         */
                         Eblock
                    ETan

                    EGAL(fin_de_contour,VRAI);
                                        /* Ca y est, on est au bout...                                                               */
                    SEND_CONTOUR(point_courant);
                                        /* Lorsque cela est demande, on transmet les coordonnees {x,y} du point                      */
                                        /* d'arrivee du contour qui est aussi le vrai point de depart...                             */
                    Eblock
               ETes
               Eblock
          ETes
          Eblock
     ETes

     Test(IFOU(EST_FAUX(fin_de_contour)
              ,EST_FAUX(un_point_au_moins_a_ete_emis)
               )
          )
          Bblock
          EGAL(fin_de_contour,VRAI);
          SEND_CONTOUR(point_courant);
                                        /* Le 19990603092111 ce dispositif a ete ajoute afin d'eviter le blocage de l'eventuel       */
                                        /* processus 'processus_recepteur' si 'IL_FAUT(emission_des_points)' dans le cas ou une      */
                                        /* erreur se serait produite (par exemple, pour inexistence du contour).                     */
          Eblock
     ATes
          Bblock
          Eblock
     ETes

     RETI(imageR);
     Eblock

#undef    SEND_CONTOUR

#undef    LE_POINT_VOISIN_EST_IL_A_L_INTERIEUR

#undef    DEPLACEMENT_POINT
#undef    ALLER_A_DROITE
#undef    gALLER_A_DROITE
#undef    ALLER_A_GAUCHE
#undef    gALLER_A_GAUCHE

EFonctionP

_______________________________________________________________________________________________________________________________________
_______________________________________________________________________________________________________________________________________
/*===================================================================================================================================*/
/*************************************************************************************************************************************/
/*                                                                                                                                   */
/*        E X T R A C T I O N   D E   T O U S   L E S   C O N T O U R S   D ' U N E   I M A G E  :                                   */
/*                                                                                                                                   */
/*************************************************************************************************************************************/

BFonctionP

#define   SEUIL_DES_CONTOURS                                                                                                            \
                    GRIS                                                                                                                \
                                        /* Pour la phase finale de binarisation...                                                   */

DEFV(Common,DEFV(FonctionP,POINTERp(Iextraction_contours(imageR,imageA,seuil_du_contour))))
DEFV(Argument,DEFV(image,imageR));
                                        /* Image Resultat contenant le contour extrait depuis l'image Argument.                      */
DEFV(Argument,DEFV(image,imageA));
                                        /* Image Argument.                                                                           */
DEFV(Argument,DEFV(genere_p,seuil_du_contour));
                                        /* Niveau definissant ce qui est a l'exterieur et ce qui est a l'interieur                   */
                                        /* du contour :                                                                              */
                                        /* les points de niveau inferieur ou egal a 'seuil' sont exterieurs, et                      */
                                        /* les points de niveau strictement superieur a 'seuil' sont interieurs.                     */
/*-----------------------------------------------------------------------------------------------------------------------------------*/
     Bblock
     BDEFV(image,interieur);
                                        /* Image de type masque definissant l'interieur des contours.                                */
     /*..............................................................................................................................*/
     CALS(Ibinarisation(interieur,imageA,seuil_du_contour));
                                        /* Recherche de l'interieur de tous les contours.                                            */
     CALS(Ijeu_de_la_vie_generalise(imageR,interieur));
                                        /* Et extraction "douce" des contours...                                                     */
     CALS(Ibinarisation(imageR,imageR,SEUIL_DES_CONTOURS));
                                        /* Et enfin, binarisation du resultat...                                                     */

     EDEFV(image,interieur);
                                        /* Image de type masque definissant l'interieur des contours.                                */

     RETI(imageR);
     Eblock

#undef    SEUIL_DES_CONTOURS

EFonctionP

_______________________________________________________________________________________________________________________________________
_______________________________________________________________________________________________________________________________________
/*===================================================================================================================================*/
/*************************************************************************************************************************************/
/*                                                                                                                                   */
/*        E X T R A C T I O N   D ' U N E   L I G N E   D E   P L U S   G R A N D E   P E N T E  :                                   */
/*                                                                                                                                   */
/*************************************************************************************************************************************/

BFonctionP

#define   NOMBRE_DE_POINTS_MAXIMAL                                                                                                      \
                    EXP2(PAR1(DOUB(efficacite_de_l_effet_tunnel)))                                                                      \
                                        /* Nombre de points que l'on traitera au maximum sur une spirale ; ce                        */ \
                                        /* parametre donne l'efficacite de l'"effet tunnel" qui permet de sortir                     */ \
                                        /* certaines impasses...                                                                     */
#define   TEST_VOISINAGE(condition,direction,x,y)                                                                                       \
                                        /* Cette procedure regarde si le point courant {x,y} est successeur possible                 */ \
                                        /* au point courant de la ligne de plus grand pente ; celui-ci doit d'abord                  */ \
                                        /* etre dans l'image, puis avoir un niveau inferieur a celui du point courant                */ \
                                        /* de la ligne de plus grande pente, et enfin etre possede le plus petit niveau              */ \
                                        /* du voisinage de ce fameux point courant.                                                  */ \
                    Bblock                                                                                                              \
                    DEFV(Int,INIT(niveau_courant,NIVEAU_UNDEF));                                                                        \
                                        /* Destine a contenir le niveau du point courant {x,y}.                                      */ \
                    Test(IL_FAUT(direction))                                                                                            \
                         Bblock                                                                                                         \
                         Test(TEST_DANS_L_IMAGE(x,y))                                                                                   \
                              Bblock                                                                                                    \
                              Test(TEST_POINT_NON_MARQUE(x,y))                                                                          \
                                   Bblock                                                                                               \
                                        /* On ne traite que les points sur lesquels on n'est pas encore passe ; on                   */ \
                                        /* notera qu'il serait imprudent de tester 'NIVEAU_DE_MARQUAGE' avec                         */ \
                                        /* un 'IFEQ' a cause des problemes lies aux 'liste de substitution'.                         */ \
                                   EGAL(niveau_courant,load_point(imageA,x,y));                                                         \
                                        /* Initialisation du niveau du point courant {x,y}.                                          */ \
                                   Test(IFET(condition(niveau_courant,niveau_courant_sur_la_ligne)                                      \
                                            ,condition(niveau_courant,niveau_courant_dans_le_voisinage)                                 \
                                             )                                                                                          \
                                        )                                                                                               \
                                        Bblock                                                                                          \
                                        EGAL(X_voisin,x);                                                                               \
                                        EGAL(Y_voisin,y);                                                                               \
                                        EGAL(niveau_courant_dans_le_voisinage,niveau_courant);                                          \
                                        /* Lorsqu'on a trouve un point {x,y} dont le niveau est le plus petit de tous                */ \
                                        /* ceux du voisinage (et plus petit aussi que le point courant de la ligne,                  */ \
                                        /* on le prend comme eventuel futur point "directeur" du point courant sur                   */ \
                                        /* la ligne.                                                                                 */ \
                                        EGAL(on_a_trouve_au_moins_un_voisin,VRAI);                                                      \
                                        /* Et on memorise que l'on a trouve au moins un futur successeur...                          */ \
                                        Eblock                                                                                          \
                                   ATes                                                                                                 \
                                        Bblock                                                                                          \
                                        Eblock                                                                                          \
                                   ETes                                                                                                 \
                                   Eblock                                                                                               \
                              ATes                                                                                                      \
                                   Bblock                                                                                               \
                                   Eblock                                                                                               \
                              ETes                                                                                                      \
                              Eblock                                                                                                    \
                         ATes                                                                                                           \
                              Bblock                                                                                                    \
                              Eblock                                                                                                    \
                         ETes                                                                                                           \
                         Eblock                                                                                                         \
                    ATes                                                                                                                \
                         Bblock                                                                                                         \
                         Eblock                                                                                                         \
                    ETes                                                                                                                \
                    Eblock

DEFV(Common,DEFV(FonctionP,POINTERp(Iextraction_ligne_de_plus_grande_pente(imageR
                                                                          ,ARGUMENT_POINTERs(point_d_arrivee)
                                                                          ,imageA
                                                                          ,ARGUMENT_POINTERs(point_de_depart)
                                                                          ,est_______,nord______,ouest_____,sud_______
                                                                          ,nord_est__,nord_ouest,sud_ouest_,sud_est___
                                                                          ,niveau_de_marquage_de_la_ligne
                                                                          ,nombre_de_points_maximal
                                                                          ,efficacite_de_l_effet_tunnel
                                                                           )
                                    )
                 )
     )
DEFV(Argument,DEFV(image,imageR));
                                        /* Image Resultat contenant le contour extrait depuis l'image Argument.                      */
DEFV(Argument,DEFV(pointF_2D,POINTERs(point_d_arrivee)));
                                        /* Coordonnees du point d'arrivee d'extraction de la ligne de plus grande                    */
                                        /* pente exprimees dans des unites telles que l'unite vaut respectivement                    */
                                        /* [Xmin,Xmax] et [Ymin,Ymax] ; il s'agit en general d'une impasse, et donc                  */
                                        /* en exploitant ce point et en utilisant le remplissage de contours progressif              */
                                        /* autour de lui, on peut "combler" le trou dans lequel on est tombe...                      */
DEFV(Argument,DEFV(image,imageA));
                                        /* Image Argument.                                                                           */
DEFV(Argument,DEFV(pointF_2D,POINTERs(point_de_depart)));
                                        /* Coordonnees du point de depart d'extraction de la ligne de plus grande                    */
                                        /* pente exprimees dans des unites telles que l'unite vaut respectivement                    */
                                        /* [Xmin,Xmax] et [Ymin,Ymax].                                                               */
DEFV(Argument,DEFV(Logical,est_______));
                                        /* Variable logique indiquant si l'on doit emprunter la direction 'est'                      */
                                        /* ('VRAI') ou pas ('FAUX') lors de l'exploration du vosinage du point courant.              */
DEFV(Argument,DEFV(Logical,nord______));
                                        /* Variable logique indiquant si l'on doit emprunter la direction 'nord'                     */
                                        /* ('VRAI') ou pas ('FAUX') lors de l'exploration du vosinage du point courant.              */
DEFV(Argument,DEFV(Logical,ouest_____));
                                        /* Variable logique indiquant si l'on doit emprunter la direction 'ouest'                    */
                                        /* ('VRAI') ou pas ('FAUX') lors de l'exploration du vosinage du point courant.              */
DEFV(Argument,DEFV(Logical,sud_______));
                                        /* Variable logique indiquant si l'on doit emprunter la direction 'sud'                      */
                                        /* ('VRAI') ou pas ('FAUX') lors de l'exploration du vosinage du point courant.              */
DEFV(Argument,DEFV(Logical,nord_est__));
                                        /* Variable logique indiquant si l'on doit emprunter la direction 'nord_est'                 */
                                        /* ('VRAI') ou pas ('FAUX') lors de l'exploration du vosinage du point courant.              */
DEFV(Argument,DEFV(Logical,nord_ouest));
                                        /* Variable logique indiquant si l'on doit emprunter la direction 'nord_ouest'               */
                                        /* ('VRAI') ou pas ('FAUX') lors de l'exploration du vosinage du point courant.              */
DEFV(Argument,DEFV(Logical,sud_ouest_));
                                        /* Variable logique indiquant si l'on doit emprunter la direction 'sud_ouest'                */
                                        /* ('VRAI') ou pas ('FAUX') lors de l'exploration du vosinage du point courant.              */
DEFV(Argument,DEFV(Logical,sud_est___));
                                        /* Variable logique indiquant si l'on doit emprunter la direction 'sud_est'                  */
                                        /* ('VRAI') ou pas ('FAUX') lors de l'exploration du vosinage du point courant.              */
DEFV(Argument,DEFV(genere_p,niveau_de_marquage_de_la_ligne));
                                        /* Niveau a utiliser pour remplir le contour Argument.                                       */
DEFV(Argument,DEFV(Int,nombre_de_points_maximal));
                                        /* Nombre de points maximal demande sur la ligne de plus grande pente.                       */
DEFV(Argument,DEFV(Int,efficacite_de_l_effet_tunnel));
                                        /* Ce parametre donne la demi-taille maximale du cote de la spirale ; plus                   */
                                        /* il est grand et plus on pourra s'echapper des impasses...                                 */
/*-----------------------------------------------------------------------------------------------------------------------------------*/
     Bblock
     DEFV(Int,INIT(nombre_de_points_sur_la_ligne,ZERO));
                                        /* Compteur des points generes sur la ligne de plus grande pente.                            */
     DEFV(pointI_2D,point_courant_sur_la_ligne);
                                        /* Point courant de la ligne de plus grande pente dans [Xmin,Xmax][Ymin,Ymax].               */
     DEFV(Logical,INIT(on_a_trouve_au_moins_un_successeur,FAUX));
                                        /* Indicateur montrant si au moins un successeur a ete rencontre sur la ligne                */
                                        /* de plus grande pente.                                                                     */
     DEFV(genere_p,INIT(niveau_courant_sur_la_ligne,NIVEAU_UNDEF));
                                        /* Niveau du point courant de la ligne de plus grande pente dans 'imageA' ; il               */
                                        /* sera initialise sur le point de depart, et la valeur qu'il contient ne peut               */
                                        /* theoriquement decroitre puisque l'on recherche la ligne de plus grande pente ;            */
                                        /* en fait, cela n'est pas tout a fait vrai, car pour eviter de tomber dans                  */
                                        /* des "impasses", on met en place une sorte d'"effet tunnel"...                             */
     SPIRALE_DEFINITION
                                        /* Donnees de generation d'une spirale de parcours d'une image.                              */
     DEFV(pointI_2D,point_courant);
                                        /* Point courant sur la spirale ; le premier point traite n'est pas le                       */
                                        /* centre afin d'etre sur de se deplacer.                                                    */
     DEFV(Logical,INIT(on_a_trouve_au_moins_un_voisin,LUNDEF));
                                        /* Indicateur montrant si au moins un voisin interessant a ete rencontre.                    */
     DEFV(Int,INIT(X_voisin,UNDEF));
                                        /* Abscisse d'un voisin interessant en tant que "direction" du futur successeur,             */
     DEFV(Int,INIT(Y_voisin,UNDEF));
                                        /* Ordonnee d'un voisin interessant en tant que "direction" du futur successeur.             */
     DEFV(genere_p,INIT(niveau_courant_dans_le_voisinage,NIVEAU_UNDEF));
                                        /* Niveau courant d'un point du voisinage du point_courant_sur_la_ligne.                     */
     /*..............................................................................................................................*/
     MARQUAGE_VALIDATION_ET_INITIALISATION;
                                        /* On verifie que le marquage est possible...                                                */
     SPIRALE_VALIDATION;
                                        /* Validation des pas de parcours (pasX,pasY) des images.                                    */
     INITIALISATION_POINT_2D(point_courant_sur_la_ligne
                            ,_cDENORMALISE_OX(ASI1(point_de_depart,x))
                            ,_cDENORMALISE_OY(ASI1(point_de_depart,y))
                             );
                                        /* Recuperation des coordonnees du point de depart demande, et mise dans les                 */
                                        /* coordonnees de l'image, afin de d'initialiser le point courant sur la                     */
                                        /* ligne de plus grande pente.                                                               */
     Test(TEST_HORS_IMAGE(ASD1(point_courant_sur_la_ligne,x),ASD1(point_courant_sur_la_ligne,y)))
          Bblock
          PRINT_ERREUR("le point de depart est hors de l'image");
          Eblock
     ATes
          Bblock
          EGAL(on_a_trouve_au_moins_un_successeur,VRAI);
                                        /* En fait, le premier successeur est le point de depart...                                  */

          Tant(EST_VRAI(on_a_trouve_au_moins_un_successeur))
               Bblock
               EGAL(niveau_courant_sur_la_ligne
                   ,load_point(imageA,ASD1(point_courant_sur_la_ligne,x),ASD1(point_courant_sur_la_ligne,y))
                    );
                                        /* Initialisation du niveau du point courant sur la ligne de plus grande pente               */
                                        /* sur le point de depart la premiere fois, et sur le point courant de la ligne              */
                                        /* de plus grande pente les fois suivantes...                                                */
               MARQUAGE_POINT(ASD1(point_courant_sur_la_ligne,x),ASD1(point_courant_sur_la_ligne,y));
                                        /* On memorise le passage par ce point...                                                    */
               store_point(niveau_de_marquage_de_la_ligne
                          ,imageR
                          ,ASD1(point_courant_sur_la_ligne,x),ASD1(point_courant_sur_la_ligne,y)
                          ,FVARIABLE
                           );
                                        /* Marquage du point courant...                                                              */
               TRANSFERT_POINT_2D(point_courant,point_courant_sur_la_ligne);
                                        /* Definition du centre de la spirale de recherche de la direction du                        */
                                        /* successeur du point courant ; cette spirale est destinee a voir dans                      */
                                        /* quelle direction par rapport au point courant se trouve probablement                      */
                                        /* la suite de la ligne de plus grande pente.                                                */
               EGAL(niveau_courant_dans_le_voisinage,BLANC);
                                        /* Les tests etants "stricts" ('IFLT'), on initialise sans probleme le plus                  */
                                        /* petit niveau rencontre sur le plus grand possible ('BLANC').                              */
               EGAL(on_a_trouve_au_moins_un_voisin,FAUX);
                                        /* On indique ainsi que l'on a encore rencontre aucun voisin interessant...                  */

               TEST_VOISINAGE(IFLT,est_______,SUCX(ASD1(point_courant,x)),NEUT(ASD1(point_courant,y)));
               TEST_VOISINAGE(IFLT,nord______,NEUT(ASD1(point_courant,x)),SUCY(ASD1(point_courant,y)));
               TEST_VOISINAGE(IFLT,ouest_____,PREX(ASD1(point_courant,x)),NEUT(ASD1(point_courant,y)));
               TEST_VOISINAGE(IFLT,sud_______,NEUT(ASD1(point_courant,x)),PREY(ASD1(point_courant,y)));
               TEST_VOISINAGE(IFLT,nord_est__,SUCX(ASD1(point_courant,x)),SUCY(ASD1(point_courant,y)));
               TEST_VOISINAGE(IFLT,nord_ouest,PREX(ASD1(point_courant,x)),SUCY(ASD1(point_courant,y)));
               TEST_VOISINAGE(IFLT,sud_ouest_,PREX(ASD1(point_courant,x)),PREY(ASD1(point_courant,y)));
               TEST_VOISINAGE(IFLT,sud_est___,SUCX(ASD1(point_courant,x)),PREY(ASD1(point_courant,y)));
                                        /* Ainsi, on examine exhaustivement le voisinage du point courant, afin de trouver           */
                                        /* s'il existe un "vrai" plus petit niveau voisin de celui-ci...                             */

               Test(EST_FAUX(on_a_trouve_au_moins_un_voisin))
                    Bblock
                                        /* Lorsque celui-ci n'existe pas, on regarde alors a niveau constant ; pour                  */
                                        /* des raisons liees aux tests de 'TEST_VOISINAGE' et a l'initialisation                     */
                                        /* a 'BLANC' de 'niveau_courant_dans_le_voisinage', on utilise 'IFLE' et                     */
                                        /* non pas 'IFEQ'...                                                                         */
                    TEST_VOISINAGE(IFLE,est_______,SUCX(ASD1(point_courant,x)),NEUT(ASD1(point_courant,y)));
                    TEST_VOISINAGE(IFLE,nord______,NEUT(ASD1(point_courant,x)),SUCY(ASD1(point_courant,y)));
                    TEST_VOISINAGE(IFLE,ouest_____,PREX(ASD1(point_courant,x)),NEUT(ASD1(point_courant,y)));
                    TEST_VOISINAGE(IFLE,sud_______,NEUT(ASD1(point_courant,x)),PREY(ASD1(point_courant,y)));
                    TEST_VOISINAGE(IFLE,nord_est__,SUCX(ASD1(point_courant,x)),SUCY(ASD1(point_courant,y)));
                    TEST_VOISINAGE(IFLE,nord_ouest,PREX(ASD1(point_courant,x)),SUCY(ASD1(point_courant,y)));
                    TEST_VOISINAGE(IFLE,sud_ouest_,PREX(ASD1(point_courant,x)),PREY(ASD1(point_courant,y)));
                    TEST_VOISINAGE(IFLE,sud_est___,SUCX(ASD1(point_courant,x)),PREY(ASD1(point_courant,y)));

                    Test(EST_FAUX(on_a_trouve_au_moins_un_voisin))
                         Bblock
                                        /* Lorsque celui-ci n'existe pas, on regarde anarchiquement le voisinage,                    */
                                        /* avec mise en place d'uune "effet tunnel" qui permet de franchir les                       */
                                        /* barrieres de niveaux trop eleves...                                                       */
                         SPIRALE_REINITIALISATION_BRAS_ET_DELTAS;
                                        /* Reinitialisation de la spirale en son centre, sans reinitialiser la direction et le sens  */
                                        /* du bras courant. Puis,                                                                    */
                                        /* reinitialisation de (spirale_delta_horizontal,spirale_delta_vertical) qui donne la        */
                                        /* direction et le sens du bras courant de la spirale.                                       */
                         SPIRALE_REINITIALISATION_COMPTAGE;
                                        /* Afin de compter les nombres de points de la spirale que l'on traite...                    */

                         Tant(IFET(EST_FAUX(on_a_trouve_au_moins_un_voisin)
                                  ,IFLT(nombre_de_points_sur_la_spirale,NOMBRE_DE_POINTS_MAXIMAL)
                                   )
                              )
                              Bblock
                                        /* Ainsi, on cherche "en spirale" le premier point qui donne la direction                    */
                                        /* dans laquelle la densite des points semble diminuer...                                    */
                              SPIRALE_INITIALISATION;
                                        /* Initialisation dynamique de 'spirale_nombre_de_points_a_traiter'.                         */
                              SPIRALE_DEPLACEMENT(ASD1(point_courant,x),ASD1(point_courant,y));
                                        /* Et on deplace le point courant avant les tests sur le bras courant, et ce                 */
                                        /* afin d'etre sur de se deplacer.                                                           */
                                        /* ATTENTION : on n'utilise pas 'SPIRALE_DEPLACEMENT_ET_PARCOURS(...)' afin de garantir la   */
                                        /* terminaison du processus 'Tant(...)'.                                                     */
                              TEST_VOISINAGE(IFLT,VRAI,ASD1(point_courant,x),ASD1(point_courant,y));
                                        /* Test du voisinage du point courant ; cette fonction 'TEST_VOISINAGE' est                  */
                                        /* laissee la pour des raisons historiques : elles permettaient de choisir                   */
                                        /* les directions de test (premier argument 'VRAI').                                         */
                              SPIRALE_PARCOURS;
                                        /* Parcours de la spirale avec rotation eventuelle de PI/2 du bras courant...                */
                              SPIRALE_COMPTAGE;
                                        /* Et on calcule le nombre de points que l'on a traite (quel que soit leur etat).            */
                              Eblock
                         ETan
                         Eblock
                    ATes
                         Bblock
                         Eblock
                    ETes
                    Eblock
               ATes
                    Bblock
                    Eblock
               ETes

               Test(EST_VRAI(on_a_trouve_au_moins_un_voisin))
                    Bblock
                    INCR(ASD1(point_courant_sur_la_ligne,x)
                        ,COND(IFGT(X_voisin,ASD1(point_courant_sur_la_ligne,x))
                             ,pasX
                             ,COND(IFLT(X_voisin,ASD1(point_courant_sur_la_ligne,x))
                                  ,NEGA(pasX)
                                  ,ZERO
                                   )
                              )
                         );
                    INCR(ASD1(point_courant_sur_la_ligne,y)
                        ,COND(IFGT(Y_voisin,ASD1(point_courant_sur_la_ligne,y))
                             ,pasY
                             ,COND(IFLT(Y_voisin,ASD1(point_courant_sur_la_ligne,y))
                                  ,NEGA(pasY)
                                  ,ZERO
                                   )
                              )
                         );
                                        /* On a trouve un successeur, qui est en fait le "meilleur" voisin, c'est-a-dire             */
                                        /* celui qui est dans la direction d'un point eventuellement eloigne, et dont                */
                                        /* le niveau est le plus eloigne par valeur inferieure de celui du point                     */
                                        /* courant...                                                                                */
                    Eblock
               ATes
                    Bblock
                    Eblock
               ETes

               INCR(nombre_de_points_sur_la_ligne,I);
                                        /* Et on compte les points generes sur la ligne de plus grande pente...                      */

               Test(IFOU(EST_FAUX(on_a_trouve_au_moins_un_voisin)
                        ,IFGE(nombre_de_points_sur_la_ligne,nombre_de_points_maximal)
                         )
                    )
                    Bblock
                    EGAL(on_a_trouve_au_moins_un_successeur,FAUX);
                                        /* Lorsque l'on n'a trouve aucun voisin (ou que l'on a genere trop de                        */
                                        /* points, ce nombre ne pouvant exceder le nombre de couleurs puisque                        */
                                        /* les tests sur les niveaux decroissent strictement), on s'arrete...                        */
                    Eblock
               ATes
                    Bblock
                    Eblock
               ETes
               Eblock
          ETan

          EGAL(ASI1(point_d_arrivee,x),_____cNORMALISE_OX(ASD1(point_courant_sur_la_ligne,x)));
          EGAL(ASI1(point_d_arrivee,y),_____cNORMALISE_OY(ASD1(point_courant_sur_la_ligne,y)));
                                        /* Renvoi des coordonnees du point d'arrivee de la ligne de plus grande pente...             */
          Eblock
     ETes

     RETI(imageR);
     Eblock

#undef    TEST_VOISINAGE
#undef    NOMBRE_DE_POINTS_MAXIMAL

EFonctionP

_______________________________________________________________________________________________________________________________________
_______________________________________________________________________________________________________________________________________
/*===================================================================================================================================*/
/*************************************************************************************************************************************/
/*                                                                                                                                   */
/*        C A L C U L   D E S   D I S T A N C E S   A U X   B O R D S   D ' U N E   I M A G E  :                                     */
/*                                                                                                                                   */
/*                                                                                                                                   */
/*        Principe :                                                                                                                 */
/*                                                                                                                                   */
/*                    Cette fonction est destinee a calculer                                                                         */
/*                  les distances respectives aux quatre bords                                                                       */
/*                  de l'image.                                                                                                      */
/*                                                                                                                                   */
/*                                                                                                                                   */
/*                                                                   bord du haut                                                    */
/*                                                Ymax  --------------------------------------                                       */
/*                                                     |          .                           |                                      */
/*                                                     |          .        niveaux<=seuil     |                                      */
/*                                                     |          .                           |                                      */
/*                                                     |        Dh.     ***                   |                                      */
/*                                                     |          .    ** ***                 |                                      */
/*                                                     |          .   **    ****              |                                      */
/*                                                     |          . ***        *****    Dd    |                                      */
/*                                                     |          ***              *..........|                                      */
/*                                      bord de gauche |         **                *          | bord de droite                       */
/*                                                     |         *                **          |                                      */
/*                                                     |   Dg    *               **           |                                      */
/*                                                     |.........**             **            |                                      */
/*                                                     |          ****        ***             |                                      */
/*                                                     |             ***   ****               |                                      */
/*                                                     |               *****    niveaux<=seuil|                                      */
/*                                                     |                  .                   |                                      */
/*                                                     |  niveaux<=seuil  .Db                 |                                      */
/*                                                     |                  .                   |                                      */
/*                                                Ymin  --------------------------------------                                       */
/*                                                    Xmin            bord du bas           Xmax                                     */
/*                                                                                                                                   */
/*                                                                                                                                   */
/*************************************************************************************************************************************/

BFonctionP

#define   NIVEAU_DE_MARQUAGE_DU_BAS                                                                                                     \
                    GRIS_1                                                                                                              \
                                        /* Niveau de generation des points du bas dans 'imageR',                                     */
#define   NIVEAU_DE_MARQUAGE_DU_HAUT                                                                                                    \
                    GRIS_3                                                                                                              \
                                        /* Niveau de generation des points du haut dans 'imageR'.                                    */
#define   NIVEAU_DE_MARQUAGE_DE_LA_GAUCHE                                                                                               \
                    GRIS_5                                                                                                              \
                                        /* Niveau de generation des points de la gauche dans 'imageR',                               */
#define   NIVEAU_DE_MARQUAGE_DE_LA_DROITE                                                                                               \
                    GRIS_7                                                                                                              \
                                        /* Niveau de generation des points de la droite dans 'imageR'.                               */

DEFV(Common,DEFV(FonctionP,POINTERp(Icalcul_des_distances_aux_bords(imageR
                                                                   ,bord_du_bas
                                                                   ,bord_du_haut
                                                                   ,bord_de_gauche
                                                                   ,bord_de_droite
                                                                   ,imageA
                                                                   ,seuil_du_contour
                                                                    )
                                    )
                 )
     )
DEFV(Argument,DEFV(image,imageR));
                                        /* Image Resultat dans laquelle on porte les points extraits.                                */
DEFV(Argument,DEFV(ligneF,bord_du_bas));
                                        /* Distances flottantes dans [0,1] au bord du bas des premiers points                        */
                                        /* de niveau superieur ou egal au seuil argument,                                            */
DEFV(Argument,DEFV(ligneF,bord_du_haut));
                                        /* Distances flottantes dans [0,1] au bord du haut des premiers points                       */
                                        /* de niveau superieur ou egal au seuil argument.                                            */
DEFV(Argument,DEFV(colonneF,bord_de_gauche));
                                        /* Distances flottantes dans [0,1] au bord de gauche des premiers points                     */
                                        /* de niveau superieur ou egal au seuil argument,                                            */
DEFV(Argument,DEFV(colonneF,bord_de_droite));
                                        /* Distances flottantes dans [0,1] au bord de droite des premiers points                     */
                                        /* de niveau superieur ou egal au seuil argument.                                            */
DEFV(Argument,DEFV(image,imageA));
                                        /* Image Argument.                                                                           */
DEFV(Argument,DEFV(genere_p,seuil_du_contour));
                                        /* Niveau definissant ce qui est a l'exterieur et ce qui est a l'interieur                   */
                                        /* du pseudo contour que l'on recherche ainsi :                                              */
                                        /* les points de niveau inferieur ou egal a 'seuil' sont exterieurs, et                      */
                                        /* les points de niveau strictement superieur a 'seuil' sont interieurs.                     */
/*-----------------------------------------------------------------------------------------------------------------------------------*/
     Bblock
     /*..............................................................................................................................*/
     begin_ligne
          Bblock
          EGAL(LIGNE(bord_du_haut,X,Ymin),_____cNORMALISE_OY(PREY(Ymin)));
          EGAL(LIGNE(bord_du_bas,X,Ymin),_____cNORMALISE_OY(SUCY(Ymax)));
                                        /* Initialisation du haut et du bas pour la verticale 'X' courante.                          */

          begin_colonne
               Bblock
               Test(IFGT(load_point(imageA,X,Y),seuil_du_contour))
                    Bblock
                    EGAL(LIGNE(bord_du_haut,X,Y),MAX2(_____cNORMALISE_OY(Y),LIGNE(bord_du_haut,X,Y)));
                    EGAL(LIGNE(bord_du_bas,X,Y),MIN2(_____cNORMALISE_OY(Y),LIGNE(bord_du_bas,X,Y)));
                                        /* Calcul du haut et du bas pour la verticale 'X' courante                                   */
                                        /* lorsque le niveau du point courant {X,Y} depasse le seuil.                                */
                    Eblock
               ATes
                    Bblock
                    Eblock
               ETes
               Eblock
          end_colonne

          store_point_valide(NIVEAU_DE_MARQUAGE_DU_BAS
                            ,imageR
                            ,X,_cDENORMALISE_OY(LIGNE(bord_du_bas,X,Ymin))
                            ,FVARIABLE
                             );
          store_point_valide(NIVEAU_DE_MARQUAGE_DU_HAUT
                            ,imageR
                            ,X,_cDENORMALISE_OY(LIGNE(bord_du_haut,X,Ymin))
                            ,FVARIABLE
                             );
          Eblock
     end_ligne

     begin_colonne
          Bblock
          EGAL(COLONNE(bord_de_droite,Xmin,Y),_____cNORMALISE_OX(PREX(Xmin)));
          EGAL(COLONNE(bord_de_gauche,Xmin,Y),_____cNORMALISE_OX(SUCX(Xmax)));
                                        /* Initialisation de la droite et de la gauche pour l'horizontale 'Y' courante.              */
          begin_ligne
               Bblock
               Test(IFGT(load_point(imageA,X,Y),seuil_du_contour))
                    Bblock
                    EGAL(COLONNE(bord_de_droite,X,Y),MAX2(_____cNORMALISE_OX(X),COLONNE(bord_de_droite,X,Y)));
                    EGAL(COLONNE(bord_de_gauche,X,Y),MIN2(_____cNORMALISE_OX(X),COLONNE(bord_de_gauche,X,Y)));
                                        /* Calcul de la droite et de la gauche pour l'horizontale 'Y' courante                       */
                                        /* lorsque le niveau du point courant {X,Y} depasse le seuil.                                */
                    Eblock
               ATes
                    Bblock
                    Eblock
               ETes
               Eblock
          end_ligne

          store_point_valide(NIVEAU_DE_MARQUAGE_DE_LA_DROITE
                            ,imageR
                            ,_cDENORMALISE_OX(COLONNE(bord_de_droite,Xmin,Y)),Y
                            ,FVARIABLE
                             );
          store_point_valide(NIVEAU_DE_MARQUAGE_DE_LA_GAUCHE
                            ,imageR
                            ,_cDENORMALISE_OX(COLONNE(bord_de_gauche,Xmin,Y)),Y
                            ,FVARIABLE
                             );
          Eblock
     end_colonne

     RETI(imageR);
     Eblock

#undef    NIVEAU_DE_MARQUAGE_DE_LA_DROITE
#undef    NIVEAU_DE_MARQUAGE_DE_LA_GAUCHE
#undef    NIVEAU_DE_MARQUAGE_DU_HAUT
#undef    NIVEAU_DE_MARQUAGE_DU_BAS

EFonctionP

_______________________________________________________________________________________________________________________________________



Copyright © Jean-François COLONNA, 2019-2024.
Copyright © CMAP (Centre de Mathématiques APpliquées) UMR CNRS 7641 / École polytechnique, Institut Polytechnique de Paris, 2019-2024.