/*************************************************************************************************************************************/
/*                                                                                                                                   */
/*        D E F I N I T I O N S   D E   L A   V I S U A L I S A T I O N   D ' U N E   S P H E R E  :                                 */
/*        ( F A U S S E   S P H E R E   C R E U S E   T R I D I M E N S I O N N E L L E )                                            */
/*                                                                                                                                   */
/*                                                                                                                                   */
/*        Author of '$xrq/nucleon.LS.1$I' :                                                                                          */
/*                                                                                                                                   */
/*                    Jean-Francois Colonna (LACTAMME, 1991??????????).                                                              */
/*                                                                                                                                   */
/*************************************************************************************************************************************/

/*===================================================================================================================================*/
/*************************************************************************************************************************************/
/*                                                                                                                                   */
/*        S I M U L A T I O N   D E   L A   V I S U A L I S A T I O N   D ' U N   E L L I P S O I D E   E C L A I R E  :             */
/*                                                                                                                                   */
/*************************************************************************************************************************************/
DEFV(Local,DEFV(Logical,INIT(mode_lent_mais_exact,LUNDEF)));
                                        /* Pour des raisons de compatibilite avec '$xrv/champs_5.1C$I'...                            */

#define   RANDOMISER_LA_VISUALISATION_DES_PARTICULES                                                                                    \
                    FAUX
DEFV(Local,DEFV(Logical,INIT(randomiser_la_visualisation_des_particules,RANDOMISER_LA_VISUALISATION_DES_PARTICULES)));
                                        /* Cet indicateur precise s'il faut ('VRAI') ou pas ('FAUX') randomiser l'apparence des      */
                                        /* particules.                                                                               */
#define   RAYON_INTERIEUR_RELATIF_D_UNE_PARTICULE                                                                                       \
                    FU
DEFV(Local,DEFV(Float,INIT(rayon_interieur_relatif_d_une_particule,RAYON_INTERIEUR_RELATIF_D_UNE_PARTICULE)));
                                        /* Constante destinee a definir la couche interne d'une particule a partir de laquelle on    */
                                        /* commence a "randomiser" son apparence :                                                   */
                                        /*                                                                                           */
                                        /*   =0.0 : la "randomisation" a lieu partout (a partir du centre jusqu'a la peripherie),    */
                                        /*   =1.0 : la "randomisation" est inhibee.                                                  */
                                        /*                                                                                           */
                                        /* On notera que le rayon "interieur" doit etre inferieur ou egal au rayon "exterieur"...    */
#define   RAYON_EXTERIEUR_RELATIF_D_UNE_PARTICULE                                                                                       \
                    FU
DEFV(Local,DEFV(Float,INIT(rayon_exterieur_relatif_d_une_particule,RAYON_EXTERIEUR_RELATIF_D_UNE_PARTICULE)));
                                        /* Constante destinee a definir la couche externe d'une particule en ce qui concerne le      */
                                        /* processus de "randomisation". En fait, 'rayon_exterieur_relatif_d_une_particule' permet   */
                                        /* de modifier la densite : par exemple une valeur superieur a 1.0 (par exemple 3.0) donnera */
                                        /* une forte densite de points representatifs...                                             */

#define   INTENSITE_SPECULAIRE                                                                                                          \
                    QUATRE
DEFV(Local,DEFV(Float,INIT(intensite_speculaire,FLOT(INTENSITE_SPECULAIRE))));
                                        /* Constante destinee a accentuer le caractere speculaire de l'eclairage...                  */

#define   Xc1                                                                                                                           \
                    SOUS(FLOT(X)                                                                                                        \
                        ,ASD1(centre_du_disque,x)                                                                                       \
                         )                                                                                                              \
                                        /* Abscisse centree dans le referentiel (OX1,OY1),                                           */
#define   Yc1                                                                                                                           \
                    SOUS(FLOT(Y)                                                                                                        \
                        ,ASD1(centre_du_disque,y)                                                                                       \
                         )                                                                                                              \
                                        /* Ordonnee centree dans le referentiel (OX1,OY1).                                           */

#define   Xc2(direction_axe,grand_axe_a,petit_axe_b)                                                                                    \
                    DIVI(LIZ2(NEUT(ASD1(direction_axe,dx)),Xc1                                                                          \
                             ,NEUT(ASD1(direction_axe,dy)),Yc1                                                                          \
                              )                                                                                                         \
                        ,grand_axe_a                                                                                                    \
                         )                                                                                                              \
                                        /* Abscisse ramenee au grand axe 'a', suppose non nul, dans le referentiel (OX2,OY2),        */
#define   Yc2(direction_axe,grand_axe_a,petit_axe_b)                                                                                    \
                    DIVI(LIZ2(NEGA(ASD1(direction_axe,dy)),Xc1                                                                          \
                             ,NEUT(ASD1(direction_axe,dx)),Yc1                                                                          \
                              )                                                                                                         \
                        ,petit_axe_b                                                                                                    \
                         )                                                                                                              \
                                        /* Ordonnee ramenee au petit axe 'b', suppose non nul, dans le referentiel (OX2,OY2).        */

#define   Z_approxime(petit_axe_b,grand_axe_a)                                                                                          \
                    AXPB(MAX2(petit_axe_b,grand_axe_a)                                                                                  \
                        ,ASD1(vecteur_normal1,dz)                                                                                       \
                        ,ASD1(centre_du_disque,z)                                                                                       \
                         )                                                                                                              \
                                        /* Le 'Z' d'un point sur la sphere n'est pas connu exactement, mais on peut l'approximer a   */ \
                                        /* a l'aide de celui du centre et de la composante en 'Z' de la normale, qui est normalisee, */ \
                                        /* d'ou sa multiplication par le rayon 'MAX2(petit_axe_b,grand_axe_a)'...                    */

#define   DEFINITION_DU_CONTOUR_APPARENT_DE_LA_PARTICULE                                                                                \
                    FU                                                                                                                  \
                                        /* Constante destinee a definir ce qui est a l'interieur d'un contour apparent : l'interieur */ \
                                        /* correspond aux valeurs de 'equation_representative_du_contour' inferieures a cette        */ \
                                        /* constante.                                                                                */

#define   EPAISSEUR_DE_L_INTERSECTION                                                                                                   \
                    MOIT(epaisseur_de_la_couronne_d_anti_aliasing)                                                                      \
                                        /* Definition de la distance-seuil en deca de laquelle on decrete que deux spheres forment   */ \
                                        /* a cet endoit leur intersection...                                                         */

#define   niveau_RVB(niveau_RVB_du_point,nbRVB,ncRVB,iRVB)                                                                              \
                    Bblock                                                                                                              \
                    DEFV(genere_p,INIT(niveau_anterieur_du_point,load_point_valide(iRVB,X,Y)));                                         \
                                        /* Definition du niveau anterieur du point(X,Y), et ce afin d'aider le compilateur...        */ \
                    DEFV(genere_p,INIT(niveau_posterieur_du_point                                                                       \
                                      ,GENP(TRON(NIVA(HOMO(modulation_d_eclairement                                                     \
                                                          ,COORDONNEE_BARYCENTRIQUE_MINIMALE                                            \
                                                          ,COORDONNEE_BARYCENTRIQUE_MAXIMALE                                            \
                                                          ,MUL2(modulation_courante_de_la_luminance                                     \
                                                               ,FLOT(NIVR(nbRVB))                                                       \
                                                                )                                                                       \
                                                          ,MUL2(modulation_courante_de_la_luminance                                     \
                                                               ,FLOT(NIVR(ncRVB))                                                       \
                                                                )                                                                       \
                                                           )                                                                            \
                                                      )                                                                                 \
                                                ,FLOT(NOIR_PLANCHER_SUBSTITUTION)                                                       \
                                                ,FLOT__BLANC                                                                            \
                                                 )                                                                                      \
                                            )                                                                                           \
                                       )                                                                                                \
                         );                                                                                                             \
                                        /* Enfin, calcul du niveau du point courant. On notera la modulation de la luminance qui     */ \
                                        /* permet d'une part de simuler des fondus a l'ouverture et a la fermeture, et d'autre part  */ \
                                        /* de compenser la faible luminosite des premieres images due a la longueur limitee (voire   */ \
                                        /* nulle) des trainees lorsqu'il y en a...                                                   */ \
                    Test(IFNE(niveau_anterieur_du_point,niveau_posterieur_du_point))                                                    \
                         Bblock                                                                                                         \
                         EGAL(niveau_RVB_du_point                                                                                       \
                             ,NIVA(BARY(NIVR(niveau_anterieur_du_point)                                                                 \
                                       ,NIVR(niveau_posterieur_du_point)                                                                \
                                       ,correction_d_anti_aliasing_au_bord                                                              \
                                        )                                                                                               \
                                   )                                                                                                    \
                              );                                                                                                        \
                                        /* Enfin, prise en compte de la correction d'anti-aliasing ; le niveau a utiliser est donc   */ \
                                        /* interpole entre ce qui a ete calcule ('niveau_RVB_du_point') et ce qui se trouvait        */ \
                                        /* la avant ('load_point_valide(...)'), de facon a ce que tres pres du bord, le contenu      */ \
                                        /* anterieur soit preponderant :                                                             */ \
                                        /*                                                                                           */ \
                                        /*                  niveau  = h.niveau + (1-h).anterieur                                     */ \
                                        /*                                                                                           */ \
                                        /* ou 'h' designe 'correction_d_anti_aliasing_au_bord'.                                      */ \
                         Eblock                                                                                                         \
                    ATes                                                                                                                \
                         Bblock                                                                                                         \
                         EGAL(niveau_RVB_du_point                                                                                       \
                             ,niveau_posterieur_du_point                                                                                \
                              );                                                                                                        \
                                        /* Cas ou une correction n'est pas necessaire (ce test est surtout la pour eviter des        */ \
                                        /* problemes de "rebond" des splines...).                                                    */ \
                         Eblock                                                                                                         \
                    ETes                                                                                                                \
                                                                                                                                        \
                    Test(NINCff(niveau_RVB_du_point,niveau_anterieur_du_point,niveau_posterieur_du_point))                              \
                         Bblock                                                                                                         \
                         PRINT_ERREUR("un niveau interpole est mal encadre");                                                           \
                         CAL1(Prer1(" niveau anterieur          = %d\n",niveau_anterieur_du_point));                                    \
                         CAL1(Prer1(" niveau calcule            = %d\n",niveau_posterieur_du_point));                                   \
                         CAL1(Prer1(" niveau corrige            = %d\n",niveau_RVB_du_point));                                          \
                         CAL1(Prer1(" parametre d'interpolation = %g\n",correction_d_anti_aliasing_au_bord));                           \
                         Eblock                                                                                                         \
                    ATes                                                                                                                \
                         Bblock                                                                                                         \
                         Eblock                                                                                                         \
                    ETes                                                                                                                \
                    Eblock                                                                                                              \
                                        /* Calcul d'une des composantes du niveau du point courant.                                  */

#define   store_ellipsoide(nbR,nbV,nbB,ncR,ncV,ncB,iR,iV,iB,X_centre,Y_centre,Z_centre,petit_axe_b,grand_axe_a,direction_axe)           \
                                        /* ATTENTION : {X,Y,Z} E [Xmin,Xmax]x[Ymin,Ymax]x[Zmin,Zmax].                                */ \
                                        /* On notera que 'direction_axe' definit les cosinus et sinus directeurs du grand axe de     */ \
                                        /* l'ellipsoide representatif...                                                             */ \
                                        /*                                                                                           */ \
                                        /* Nota important : cette possibilite de tracer des ellipsoides projetes fut introduites     */ \
                                        /* afin de visualiser les gluons sous forme allongee (et traduisant ainsi leur deplacement), */ \
                                        /* mais malheureusement, la methode implementee ci-dessous fait que la troisieme coordonnee  */ \
                                        /* ('Z') est perdue dans le cas general, et ne peut etre reconstituee. En consequence de     */ \
                                        /* quoi, 'store_ellipsoide(...)' sera appelee dorenavant avec 'petit_axe_b=grand_axe_a', et  */ \
                                        /* la forme allongee sera representee a l'aide d'une chaine de spheres disposees le long de  */ \
                                        /* la vitesse de chaque gluon...                                                             */ \
                                        /*                                                                                           */ \
                                        /* Nota important : cette procedure est tres approximative puisque la coordonnee 'Z' de      */ \
                                        /* chaque point de la sphere est lui meme approxime de facon tres grossiere. Une solution    */ \
                                        /* a ce probleme est apporte dans '$xrv/champs_5.1C$I'.                                      */ \
                    Bblock                                                                                                              \
                    DEFV(pointF_3D,centre_du_disque);                                                                                   \
                                        /* Redefinition locale du centre du disque ; cela est rendu necessaire par le fait que       */ \
                                        /* la macro 'store_ellipsoide()' peut etre appelee avec comme argument 'X' et 'Y', qui se    */ \
                                        /* retrouveraient dans 'begin_colonneQ()' et 'begin_ligneQ()', et qui seraient donc          */ \
                                        /* confondus avec les 'X' et 'Y' locaux a ces fonctions de parcours. D'autre part, il        */ \
                                        /* est defini en 'Float' afin de conserver l'eventuelle precision des arguments d'appel...   */ \
                    DEFV(Float,INIT(equation_representative_du_contour,FLOT__UNDEF));                                                   \
                                        /* Valeur courante au point {X,Y} de la fonction representative du contour de la forme       */ \
                                        /* materialisant la particule.                                                               */ \
                    DEFV(Float,INIT(distance_normalisee_au_centre,FLOT__UNDEF));                                                        \
                                        /* Distance normalisee dans [0,1] du point courant {X,Y} au centre du disque.                */ \
                    DEFV(deltaF_3D,vecteur_normal1);                                                                                    \
                                        /*                -->                                                                        */ \
                                        /* Vecteur normal  N  au point courant de l'ellipsoide dans le referentiel (OX1,OY1), soit   */ \
                                        /* donc apres la rotation de l'angle '-t'.                                                   */ \
                    DEFV(deltaF_3D,vecteur_normal2);                                                                                    \
                                        /*                -->                                                                        */ \
                                        /* Vecteur normal  N  au point courant de l'ellipsoide dans le referentiel (OX2,OY2), soit   */ \
                                        /* donc avant la rotation de l'angle '-t'.                                                   */ \
                    DEFV(deltaF_3D,rayon_lumineux_inverse);                                                                             \
                                        /*                        -->                                                                */ \
                                        /* Rayon lumineux inverse  S  (allant du point courant de l'ellipsoide a la source           */ \
                                        /* lumineuse).                                                                               */ \
                    DEFV(Float,INIT(produit_des_modules_de_N_et_S,FLOT__UNDEF));                                                        \
                                        /*                                     -->                                                   */ \
                                        /* Produit du module du vecteur normal  N  et du module du vecteur rayon lumineux            */ \
                                        /*         -->                                                                               */ \
                                        /* inverse  S .                                                                              */ \
                    DEFV(Float,INIT(modulation_d_eclairement,FLOT__UNDEF));                                                             \
                                        /* Modulation de l'eclairement du point courant calcule a partir de l'angle entre le         */ \
                                        /*                -->                              -->                                       */ \
                                        /* vecteur normal  N  et le rayon lumineux inverse  S .                                      */ \
                                                                                                                                        \
                    INITIALISATION_DE_LA_GENERATION_D_UNE_VALEUR_SANS_DEPLACEMENT(ZERO);                                                \
                                        /* Cette reinitialisation systematique a l'entree de 'store_ellipsoide(...)' est due au fait */ \
                                        /* que la generation des images a lieu composante par composante ; 'store_ellipsoide(...)'   */ \
                                        /* est donc appele trois fois de suite pour chaque particule : il est donc absolument        */ \
                                        /* necessaire que la generation de l'aspect "random" des particules soit la meme lors des    */ \
                                        /* des trois appels...                                                                       */ \
                                                                                                                                        \
                    Test(IFNE(petit_axe_b,grand_axe_a))                                                                                 \
                         Bblock                                                                                                         \
                         PRINT_ATTENTION("dorenavant le petit axe et le grand axe doivent etre egaux");                                 \
                         Eblock                                                                                                         \
                    ATes                                                                                                                \
                         Bblock                                                                                                         \
                         Eblock                                                                                                         \
                    ETes                                                                                                                \
                                                                                                                                        \
                    CALCUL_DE_LA_DISTANCE_CRITIQUE_NORMALISEE_AU_BORD(MAX2(petit_axe_b,grand_axe_a),FLOT__UNDEF);                       \
                                        /* Preparation du traitement anti-aliasing pour cet ellipsoide particulier...                */ \
                                        /*                                                                                           */ \
                                        /* L'argument 'FLOT__UNDEF' a ete introduit le 20060224151018 ; cette valeur indifferente    */ \
                                        /* est sans consequenece car, en effet, on est ici necessairement dans le cas ou             */ \
                                        /* 'IL_NE_FAUT_PAS(moduler_l_epaisseur_de_la_couronne_d_anti_aliasing)' car d'une part       */ \
                                        /* 'IL_NE_FAUT_PAS(moduler_l_epaisseur_de_la_couronne_d_anti_aliasing)' car c'est l'etat     */ \
                                        /* defaut ('v $xrq/nucleon.LP$I MODULER_L_EPAISSEUR_DE_LA_COURONNE_D_ANTI_ALIASING') et      */ \
                                        /* cette option n'est pas activable ('v $xrq/nucleon.Lb.1$I couronne=' par exemple...).      */ \
                                                                                                                                        \
                    INITIALISATION_POINT_3D(centre_du_disque                                                                            \
                                           ,F__cDENORMALISE_OX(Projection_OX(_____cNORMALISE_OX(X_centre)                               \
                                                                            ,_____cNORMALISE_OY(Y_centre)                               \
                                                                            ,_____cNORMALISE_OZ(Z_centre)                               \
                                                                             )                                                          \
                                                               )                                                                        \
                                           ,F__cDENORMALISE_OY(Projection_OY(_____cNORMALISE_OX(X_centre)                               \
                                                                            ,_____cNORMALISE_OY(Y_centre)                               \
                                                                            ,_____cNORMALISE_OZ(Z_centre)                               \
                                                                             )                                                          \
                                                               )                                                                        \
                                           ,F__cDENORMALISE_OZ(_____cNORMALISE_OZ(Z_centre))                                            \
                                            );                                                                                          \
                                        /* Initialisation du centre effectif du disque, en se souvenant du fait que si le point      */ \
                                        /* (X_centre,Y_centre,Z_centre) etait en 'Float', la precision est conservee...              */ \
                                                                                                                                        \
                    begin_colonneQ(DoIn                                                                                                 \
                                  ,VINTE(SOUS(ASD1(centre_du_disque,y),MAX2(petit_axe_b,grand_axe_a)))                                  \
                                  ,VINTE(ADD2(ASD1(centre_du_disque,y),MAX2(petit_axe_b,grand_axe_a)))                                  \
                                  ,pasY                                                                                                 \
                                   )                                                                                                    \
                                        /* Nota : on utilise 'MAX2(petit_axe_b,grand_axe_a)' et non pas 'petit_axe_b' car en effet   */ \
                                        /* les coordonnees {X,Y} sont dans le referentiel (OX1,OY1), alors que les axes de l'ellipse */ \
                                        /* (grand_axe_a,petit_axe_b) sont mesures dans le referentiel (OX2,OY2). Ainsi, en prenant   */ \
                                        /* 'MAX2(...)' on est sur de ne pas manquer des points, meme si des calculs superflus sont   */ \
                                        /* malheureusement effectues...                                                              */ \
                                        /*                                                                                           */ \
                                        /* ATTENTION, il y avait autrefois :                                                         */ \
                                        /*                                                                                           */ \
                                        /*                  begin_colonneQ(DoIn                                                      */ \
                                        /*                                ,TRON(INTE(SOUS(...,...)),Ymin,Ymax)                       */ \
                                        /*                                ,TRON(INTE(ADD2(...,...)),Ymin,Ymax)                       */ \
                                        /*                                ,pasY                                                      */ \
                                        /*                                 )                                                         */ \
                                        /*                                                                                           */ \
                                        /* ce qui est tout a fait anormal, puisque cela ramenait sur la bordure de l'image des       */ \
                                        /* ellipsoides qui en fait en etaient en dehors...                                           */ \
                         Bblock                                                                                                         \
                         begin_ligneQ(DoIn                                                                                              \
                                     ,VINTE(SOUS(ASD1(centre_du_disque,x),MAX2(petit_axe_b,grand_axe_a)))                               \
                                     ,VINTE(ADD2(ASD1(centre_du_disque,x),MAX2(petit_axe_b,grand_axe_a)))                               \
                                     ,pasX                                                                                              \
                                      )                                                                                                 \
                                        /* Nota : on utilise 'MAX2(petit_axe_b,grand_axe_a)' et non pas 'grand_axe_a' car en effet   */ \
                                        /* les coordonnees {X,Y} sont dans le referentiel (OX1,OY1), alors que les axes de l'ellipse */ \
                                        /* (grand_axe_a,petit_axe_b) sont mesures dans le referentiel (OX2,OY2). Ainsi, en prenant   */ \
                                        /* 'MAX2(...)' on est sur de ne pas manquer des points, meme si des calculs superflus sont   */ \
                                        /* malheureusement effectues...                                                              */ \
                                        /*                                                                                           */ \
                                        /* ATTENTION, il y avait autrefois :                                                         */ \
                                        /*                                                                                           */ \
                                        /*                  begin_ligneQ(DoIn                                                        */ \
                                        /*                              ,TRON(INTE(SOUS(...,...)),Xmin,Xmax)                         */ \
                                        /*                              ,TRON(INTE(ADD2(...,...)),Xmin,Xmax)                         */ \
                                        /*                              ,pasX                                                        */ \
                                        /*                               )                                                           */ \
                                        /*                                                                                           */ \
                                        /* ce qui est tout a fait anormal, puisque cela ramenait sur la bordure de l'image des       */ \
                                        /* ellipsoides qui en fait en etaient en dehors...                                           */ \
                              Bblock                                                                                                    \
                              Test(IFOU(IZGT(petit_axe_b),IZGT(grand_axe_a)))                                                           \
                                   Bblock                                                                                               \
                                   EGAL(equation_representative_du_contour                                                              \
                                       ,ADD2(fCOND(IZGT(grand_axe_a)                                                                    \
                                                  ,EXP2(Xc2(direction_axe,grand_axe_a,petit_axe_b))                                     \
                                                  ,FZERO                                                                                \
                                                   )                                                                                    \
                                            ,fCOND(IZGT(petit_axe_b)                                                                    \
                                                  ,EXP2(Yc2(direction_axe,grand_axe_a,petit_axe_b))                                     \
                                                  ,FZERO                                                                                \
                                                   )                                                                                    \
                                             )                                                                                          \
                                        );                                                                                              \
                                        /* Valeur courante au point {X,Y} de la fonction representative du contour de la forme       */ \
                                        /* materialisant la particule. Les deux operateurs 'LIN2(...)' correspondent a une rotation  */ \
                                        /* du grand axe de l'ellipse plane (2D) de facon a ce qu'il s'aligne dans la direction       */ \
                                        /* argument 'direction_axe'. On notera que le rapport entre le grand axe et le petit         */ \
                                        /* axe est d'une part une fonction de la nature de la particule visualisee, mais aussi de    */ \
                                        /* la direction de sa vitesse par rapport a l'observateur : plus elle se situera dans le     */ \
                                        /* plan de projection, et plus l'ellipsoide sera allonge, alors qu'inversement, plus elle    */ \
                                        /* sera alignee avec l'observateur, et plus il sera spherique...                             */ \
                                        /*                                                                                           */ \
                                        /*                   -->                                                                     */ \
                                        /*                    V *                                                                    */ \
                                        /*                    *                                                                      */ \
                                        /*                  *                                                                        */ \
                                        /*                *                                                                          */ \
                                        /*       Y|     *                                                                            */ \
                                        /*        |   *                                                                              */ \
                                        /*        |                projection des deux                                               */ \
                                        /*        |______                        -->                                                 */ \
                                        /*       /O     X          extremites de  V  :                                               */ \
                                        /*      /                                                                                    */ \
                                        /*    Z/                                           Y1|                                       */ \
                                        /*                                                   |                                       */ \
                                        /*                                                   |             .                         */ \
                                        /*                                       .           | --->      . X2                        */ \
                                        /*                                      Y2 .         |  V      .                             */ \
                                        /*                                           .       |   p   *                               */ \
                                        /*                                             .     |     *                                 */ \
                                        /*                                               .   |   *                                   */ \
                                        /*                                                 . | *  \t                                 */ \
                                        /*                                                   O--------------------                   */ \
                                        /*                                                                      X1                   */ \
                                        /*                                                                                           */ \
                                        /*                                      --->                                -->              */ \
                                        /* Soit 't' l'angle que fait le vecteur  V   (projection du vecteur vitesse  V  de la        */ \
                                        /*                                        p                                                  */ \
                                        /* particule a representer) avec l'axe OX1. On a les formules de changement de coordonnees   */ \
                                        /* suivantes :                                                                               */ \
                                        /*                                                                                           */ \
                                        /*                  ( X2 )   ( +cos(t) +sin(t) ) ( X1 )                                      */ \
                                        /*                  (    ) = (                 )*(    )                                      */ \
                                        /*                  ( Y2 )   ( -sin(t) +cos(t) ) ( Y1 )                                      */ \
                                        /*                                                                                           */ \
                                        /* et                                                                                        */ \
                                        /*                                                                                           */ \
                                        /*                  ( X1 )   ( +cos(t) -sin(t) ) ( X2 )                                      */ \
                                        /*                  (    ) = (                 )*(    )                                      */ \
                                        /*                  ( Y1 )   ( +sin(t) +cos(t) ) ( Y2 )                                      */ \
                                        /*                                                                                           */ \
                                        /* Le grand axe de l'ellipse est defini par 'direction_axe' qui correspond au vecteur        */ \
                                        /* --->                                                                                      */ \
                                        /*  V   et a l'axe OX2 ; on a :                                                              */ \
                                        /*   p                                                                                       */ \
                                        /*                                                                                           */ \
                                        /*                  direction_axe = [cos(t),sin(t)].                                         */ \
                                        /*                                                                                           */ \
                                        /* L'ellipse est d'abord construite dans le referentiel (OX2,OY2), ou son equation est       */ \
                                        /* simple :                                                                                  */ \
                                        /*                                                                                           */ \
                                        /*                      2       2                                                            */ \
                                        /*                   X2      Y2                                                              */ \
                                        /*                  ----- + ----- <= 1                                                       */ \
                                        /*                     2       2                                                             */ \
                                        /*                    a       b                                                              */ \
                                        /*                                                                                           */ \
                                        /* ou 'a' designe le grand axe, et 'b' le petit axe (a >= b),                                */ \
                                        /*                                                                                           */ \
                                        /*                                                                                           */ \
                                        /* puis par rotation de l'angle '-t', on trouve son equation dans le referentiel correct     */ \
                                        /* (OX1,OY1).                                                                                */ \
                                        /*                                                                                           */ \
                                        /*                                         -->                                               */ \
                                        /* Enfin, la projection du vecteur vitesse  V  traduit, par son module, la direction de la   */ \
                                        /* particule par rapport a l'observateur : plus ce module sera petit (ce qui signifie que    */ \
                                        /* la particule va vers (ou "viens de") l'observateur ; on aura alors un grand axe voisin    */ \
                                        /* du petit axe (a ~ b), et l'apparence sera voisine d'une sphere. A l'oppose, si la         */ \
                                        /* particule se deplace dans le plan de projection, le grand axe sera maximal, et l'ellipse  */ \
                                        /* la plus allongee possible...                                                              */ \
                                        /*                                                                                           */ \
                                        /* Nota sur la degenerescence des ellipses : rappelons l'equation                            */ \
                                        /*                                                                                           */ \
                                        /*                      2       2                                                            */ \
                                        /*                   X2      Y2                                                              */ \
                                        /*                  ----- + ----- <= 1                                                       */ \
                                        /*                     2       2                                                             */ \
                                        /*                    a       b                                                              */ \
                                        /*                                                                                           */ \
                                        /* Lorsque l'un des axes est nul, l'ellipse degenere en l'autre axe, soit :                  */ \
                                        /*                                                                                           */ \
                                        /* si b=0 :                                                                                  */ \
                                        /*                                                                                           */ \
                                        /*                     2                                                                     */ \
                                        /*                   X2                                                                      */ \
                                        /*                  ----- + 0 <= 1, soit : -a <= X2 <= +a.                                   */ \
                                        /*                     2                                                                     */ \
                                        /*                    a                                                                      */ \
                                        /*                                                                                           */ \
                                        /* si a=0 :                                                                                  */ \
                                        /*                                                                                           */ \
                                        /*                         2                                                                 */ \
                                        /*                       Y2                                                                  */ \
                                        /*                  0 + ----- <= 1, soit : -b <= Y2 <= +b.                                   */ \
                                        /*                         2                                                                 */ \
                                        /*                        b                                                                  */ \
                                        /*                                                                                           */ \
                                   Eblock                                                                                               \
                              ATes                                                                                                      \
                                   Bblock                                                                                               \
                                   EGAL(equation_representative_du_contour                                                              \
                                       ,DEFINITION_DU_CONTOUR_APPARENT_DE_LA_PARTICULE                                                  \
                                        );                                                                                              \
                                        /* Lorsque les deux axes sont nuls, l'appartenance est systematique...                       */ \
                                   Eblock                                                                                               \
                              ETes                                                                                                      \
                              EGAL(distance_normalisee_au_centre                                                                        \
                                  ,RACX(equation_representative_du_contour)                                                             \
                                   );                                                                                                   \
                                        /* Calcul de la distance euclidienne normalisee du point courant {X,Y} au centre du disque.  */ \
                              Test(IFLE(distance_normalisee_au_centre,DEFINITION_DU_CONTOUR_APPARENT_DE_LA_PARTICULE))                  \
                                   Bblock                                                                                               \
                                   DEFV(Logical,INIT(marquer_le_point_courant,VRAI));                                                   \
                                        /* Cet indicateur indique s'il faut marquer le point courant ('VRAI') ou pas  ('FAUX'). Sa   */ \
                                        /* valeur initiale est choisie en faisant l'hypothese qu'il ne faut pas randomiser les       */ \
                                        /* particules (voir 'randomiser_la_visualisation_des_particules'), et que tous les points    */ \
                                        /* doivent donc etre marques...                                                              */ \
                                   DEFV(Float,INIT(distance_aleatoire_au_centre,FLOT__UNDEF));                                          \
                                        /* Valeur aleatoire permettant de determiner si le point courant {X,Y} va etre marque...     */ \
                                   DEFV(genere_p,INIT(niveau_ROUGE_du_point,ncR));                                                      \
                                   DEFV(genere_p,INIT(niveau_VERTE_du_point,ncV));                                                      \
                                   DEFV(genere_p,INIT(niveau_BLEUE_du_point,ncB));                                                      \
                                        /* Niveau du point courant initialise sur le maximum, et ce au cas ou le grand axe et le     */ \
                                        /* petit axe de l'ellipsoide seraient nuls...                                                */ \
                                   Test(IFET(IZGT(petit_axe_b),IZGT(grand_axe_a)))                                                      \
                                        /* Ce test etait autrefois :                                                                 */ \
                                        /*                                                                                           */ \
                                        /*                  Test(IZGT(MAX2(petit_axe_b,grand_axe_a)))                                */ \
                                        /*                                                                                           */ \
                                        /* mais maintenant, on prend en compte l'equation correcte de l'ellipse, alors...            */ \
                                        Bblock                                                                                          \
                                        DEFV(Float,INIT(correction_d_anti_aliasing_au_bord                                              \
                                                       ,CORRECTION_D_ANTI_ALIASING(distance_normalisee_au_centre)                       \
                                                        )                                                                               \
                                             );                                                                                         \
                                        /* En fait, 'modulation_d_eclairement' pourra etre corrige par ce facteur, car en effet,     */ \
                                        /* dans certaines circonstances, le point le plus lumineux de l'ellipsoide peut se trouver   */ \
                                        /* tres pres de son contour apparent, et donc creer un probleme d'aliasing. On calcule donc  */ \
                                        /* ici la correction en fonction du point courant par rapport au contour apparent de         */ \
                                        /* l'ellipsoide. Il convient de remarquer que la distance utilisee ici est une distance      */ \
                                        /* bidimensionnelle dans le plan, et non pas une distance dans l'espace tridimensionnel.     */ \
                                        /* Elle definie bien (ou du moins son complement a 'COORDONNEE_BARYCENTRIQUE_MAXIMALE') une  */ \
                                        /* distance du point courant bidimensionnel {X,Y} au contour apparent...                     */ \
                                        INITIALISATION_ACCROISSEMENT_3D(vecteur_normal2                                                 \
                                                                       ,Xc2(direction_axe,grand_axe_a,petit_axe_b)                      \
                                                                       ,Yc2(direction_axe,grand_axe_a,petit_axe_b)                      \
                                                                       ,RACX(SOUS(DEFINITION_DU_CONTOUR_APPARENT_DE_LA_PARTICULE        \
                                                                                 ,ADD2(EXP2(Xc2(direction_axe,grand_axe_a,petit_axe_b)) \
                                                                                      ,EXP2(Yc2(direction_axe,grand_axe_a,petit_axe_b)) \
                                                                                       )                                                \
                                                                                  )                                                     \
                                                                             )                                                          \
                                                                        );                                                              \
                                        /* Le point courant {X,Y} n'est connu que bidimensionnellement, or le calcul de la normale   */ \
                                        /* se situe dans l'espace a trois dimensions. Pour simplifier les choses, on va supposer     */ \
                                        /* que l'ellipsoide se reduit a une sphere de rayon R tel que :                              */ \
                                        /*                                                                                           */ \
                                        /*                  R = MAX2(a,b)                                                            */ \
                                        /*                                                                                           */ \
                                        /* soit en general :                                                                         */ \
                                        /*                                                                                           */ \
                                        /*                  R = a                                                                    */ \
                                        /*                                                                                           */ \
                                        /* (ou 'a' et 'b' designent respectivement le grand axe et le petit axe de l'ellipse         */ \
                                        /* obtenue par projection de l'ellipsoide).                                                  */ \
                                        /*                                                                                           */ \
                                        /* Soit donc {x,y,z} le point tridimensionnel qui projete donne {X,Y} (ou du moins l'un      */ \
                                        /* des deux puisqu'en general il y a toujours deux points de la sphere qui ont meme          */ \
                                        /* projection...) ; En supposant la sphere centree, nous avons en coordonnees spheriques :   */ \
                                        /*                                                                                           */ \
                                        /*                  x = R.cos(p).cos(t)                                                      */ \
                                        /*                  y = R.cos(p).sin(t)                                                      */ \
                                        /*                  z = R.sin(p)                                                             */ \
                                        /*                                                                                           */ \
                                        /* ou 'p' designe 'phi' et 't', 'theta'...                                                   */ \
                                        /*                                                                                           */ \
                                        /*                   -->                                                                     */ \
                                        /* Le vecteur normal  N  au point {x,y,z} est defini dans le cas d'une sphere par :          */ \
                                        /*                                                                                           */ \
                                        /*                  -->     x     y     z                                                    */ \
                                        /*                   N  = [--- , --- , ---]                                                  */ \
                                        /*                          R     R     R                                                    */ \
                                        /*                                                                                           */ \
                                        /* Ne connaissant plus {x,y,z}, on pose arbitrairement :                                     */ \
                                        /*                                                                                           */ \
                                        /*                  x = X                                                                    */ \
                                        /*                  y = Y                                                                    */ \
                                        /*                                                                                           */ \
                                        /* Or :                                                                                      */ \
                                        /*                                                                                           */ \
                                        /*                   2    2    2    2                                                        */ \
                                        /*                  x  + y  = R .cos (p)                                                     */ \
                                        /*                                                                                           */ \
                                        /* d'ou :                                                                                    */ \
                                        /*                                                                                           */ \
                                        /*                   2    2    2       2         2                                           */ \
                                        /*                  z  = R .sin (p) = R .(1 - cos (p))                                       */ \
                                        /*                                                                                           */ \
                                        /*                                 2    2                                                    */ \
                                        /*                   2    2       x  + y       2     2    2                                  */ \
                                        /*                  z  = R .(1 - ---------) = R  - (X  + Y )                                 */ \
                                        /*                                    2                                                      */ \
                                        /*                                   R                                                       */ \
                                        /*                                                                                           */ \
                                        /*                                    -->                                                    */ \
                                        /* D'ou l'approximation de la normale  N  :                                                  */ \
                                        /*                                                                                           */ \
                                        /*                                             ____________                                  */ \
                                        /*                                            /     2    2                                   */ \
                                        /*                  -->     X     Y   \      /     X  + Y                                    */ \
                                        /*                   N  = [--- , --- , \    / 1 - ---------]                                 */ \
                                        /*                          R     R     \  /           2                                     */ \
                                        /*                                       \/           R                                      */ \
                                        /*                                                                                           */ \
                                        /* ou non normalisee :                                                                       */ \
                                        /*                                                                                           */ \
                                        /*                                    ______________                                         */ \
                                        /*                  -->              / 2     2    2                                          */ \
                                        /*                   N  = [X , Y , \/ R  - (X  + Y )]                                        */ \
                                        /*                                                                                           */ \
                                        /* ce que l'on generalise courageusement en :                                                */ \
                                        /*                                                                                           */ \
                                        /*                                               __________________                          */ \
                                        /*                                              /       2       2                            */ \
                                        /*                  -->     X2     Y2   \      /      X2      Y2                             */ \
                                        /*                   N  = [---- , ---- , \    / 1 - (----- + -----)]                         */ \
                                        /*                          a      b      \  /          2       2                            */ \
                                        /*                                         \/          a       b                             */ \
                                        /*                                                                                           */ \
                                        /* qui n'est pas normalisee et se situe dans le referentiel (OX2,OY2)...                     */ \
                                        INITIALISATION_ACCROISSEMENT_3D(vecteur_normal1                                                 \
                                                                       ,LIZ2(NEUT(ASD1(direction_axe,dx))                               \
                                                                            ,ASD1(vecteur_normal2,dx)                                   \
                                                                            ,NEGA(ASD1(direction_axe,dy))                               \
                                                                            ,ASD1(vecteur_normal2,dy)                                   \
                                                                             )                                                          \
                                                                       ,LIZ2(NEUT(ASD1(direction_axe,dy))                               \
                                                                            ,ASD1(vecteur_normal2,dx)                                   \
                                                                            ,NEUT(ASD1(direction_axe,dx))                               \
                                                                            ,ASD1(vecteur_normal2,dy)                                   \
                                                                             )                                                          \
                                                                       ,ASD1(vecteur_normal2,dz)                                        \
                                                                        );                                                              \
                                        /* Puis passage du referentiel (OX2,OY2) a (OX1,OY1)...                                      */ \
                                        INITIALISATION_ACCROISSEMENT_3D(rayon_lumineux_inverse                                          \
                                                                       ,SOUS(X_DE_VISUALISATION(X_PHYSIQUE_DANS_01(ASD1(LsourceT,x)))   \
                                                                            ,FLOT(X)                                                    \
                                                                             )                                                          \
                                                                       ,SOUS(Y_DE_VISUALISATION(Y_PHYSIQUE_DANS_01(ASD1(LsourceT,y)))   \
                                                                            ,FLOT(Y)                                                    \
                                                                             )                                                          \
                                                                       ,SOUS(Z_DE_VISUALISATION(Z_PHYSIQUE_DANS_01(ASD1(LsourceT,z)))   \
                                                                            ,ADD2(ASD1(centre_du_disque,z)                              \
                                                                                 ,ASD1(vecteur_normal1,dz)                              \
                                                                                  )                                                     \
                                                                             )                                                          \
                                                                        );                                                              \
                                        /* Approximation du rayon lumineux inverse : en effet, la aussi, la coordonnee 'z' nous      */ \
                                        /* fait defaut, d'ou cette approximation obtenue en translatant le centre de l'ellipsoide a  */ \
                                        /* l'aide de la composante en 'z' du vecteur normal ; notons que cela est tres approximatif  */ \
                                        /* et ne nous amene surement pas a la surface de l'ellipsoide...                             */ \
                                        EGAL(produit_des_modules_de_N_et_S                                                              \
                                            ,RACX(MUL2(pytF3D(vecteur_normal1)                                                          \
                                                      ,pytF3D(rayon_lumineux_inverse)                                                   \
                                                       )                                                                                \
                                                  )                                                                                     \
                                             );                                                                                         \
                                        /* Calcul de :                                                                               */ \
                                        /*                                                                                           */ \
                                        /*                  --> -->                                                                  */ \
                                        /*                  |N|.|S|                                                                  */ \
                                        /*                                                                                           */ \
                                        Test(IZGT(produit_des_modules_de_N_et_S))                                                       \
                                             Bblock                                                                                     \
                                             EGAL(modulation_d_eclairement                                                              \
                                                 ,PUIX(COS1(DIVI(prdF3D(vecteur_normal1,rayon_lumineux_inverse)                         \
                                                                ,produit_des_modules_de_N_et_S                                          \
                                                                 )                                                                      \
                                                            )                                                                           \
                                                      ,intensite_speculaire                                                             \
                                                       )                                                                                \
                                                  );                                                                                    \
                                        /*               -->                   -->                                                   */ \
                                        /* Designant par  N  la normale et par  S  le rayon lumineux inverse, la modulation de       */ \
                                        /*                                                                  -->    -->               */ \
                                        /* l'eclairement s'obtient en calculant le cosinus de l'angle entre  N  et  S  :             */ \
                                        /*                                                                                           */ \
                                        /*                                  --> -->                                                  */ \
                                        /*                      --> -->      N . S                                                   */ \
                                        /*                  cos( N , S ) = ---------                                                 */ \
                                        /*                                  --> -->                                                  */ \
                                        /*                                  |N|.|S|                                                  */ \
                                        /*                                                                                           */ \
                                        /* puis en le ramenant dans [0,1] et en accentuant le phenomene (reflets speculaires)...     */ \
                                        /* L'utilisation de la fonction 'COS1(...)' a ete introduite le 19971229165528.              */ \
                                             Eblock                                                                                     \
                                        ATes                                                                                            \
                                             Bblock                                                                                     \
                                             EGAL(modulation_d_eclairement                                                              \
                                                 ,COORDONNEE_BARYCENTRIQUE_MAXIMALE                                                     \
                                                  );                                                                                    \
                                        /* Nous sommes ici dans le cas ou la particule est "tangente" a la source lumineuse...       */ \
                                             Eblock                                                                                     \
                                        ETes                                                                                            \
                                        /* Nota : il y avait ici autrefois :                                                         */ \
                                        /*                                                                                           */ \
                                        /*        EGAL(modulation_d_eclairement                                                      */ \
                                        /*            ,ADD2(COORDONNEE_BARYCENTRIQUE_MINIMALE                                        */ \
                                        /*                 ,MUL2(correction_d_anti_aliasing_au_bord                                  */ \
                                        /*                      ,SOUS(modulation_d_eclairement,COORDONNEE_BARYCENTRIQUE_MINIMALE)    */ \
                                        /*                       )                                                                   */ \
                                        /*                  )                                                                        */ \
                                        /*             );                                                                            */ \
                                        /*                                                                                           */ \
                                        /* ce qui avait l'inconvenient de faire l'hypothese que la particule que l'on marque etait   */ \
                                        /* entouree de noir (ici, on interpolait implicitement avec du noir). Ceci a ete corrige a   */ \
                                        /* l'aide d'un 'BARY(...)' entre le niveau calcule et le niveau anterieur...                 */ \
                                        Test(IFEXff(modulation_d_eclairement                                                            \
                                                   ,COORDONNEE_BARYCENTRIQUE_MINIMALE                                                   \
                                                   ,COORDONNEE_BARYCENTRIQUE_MAXIMALE                                                   \
                                                    )                                                                                   \
                                             )                                                                                          \
                                             Bblock                                                                                     \
                                             PRINT_ERREUR("la modulation d'eclairement est hors de [0,1]");                             \
                                             CAL1(Prer1(" elle vaut : %g\n",modulation_d_eclairement));                                 \
                                             CAL1(Prer1(" petit axe = %g\n",petit_axe_b));                                              \
                                             CAL1(Prer1(" grand axe = %g\n",grand_axe_a));                                              \
                                             CAL1(Prer1(" equation  = %g\n",equation_representative_du_contour));                       \
                                             CAL1(Prer1(" distance  = %g\n",distance_normalisee_au_centre));                            \
                                             CAL1(Prer1(" aliasing  = %g\n",correction_d_anti_aliasing_au_bord));                       \
                                             CAL1(Prer3(" normale N = (%g,%g,%g)\n"                                                     \
                                                       ,ASD1(vecteur_normal1,dx)                                                        \
                                                       ,ASD1(vecteur_normal1,dy)                                                        \
                                                       ,ASD1(vecteur_normal1,dz)                                                        \
                                                        )                                                                               \
                                                  );                                                                                    \
                                             CAL1(Prer3(" lumiere S = (%g,%g,%g)\n"                                                     \
                                                       ,ASD1(rayon_lumineux_inverse,dx)                                                 \
                                                       ,ASD1(rayon_lumineux_inverse,dy)                                                 \
                                                       ,ASD1(rayon_lumineux_inverse,dz)                                                 \
                                                        )                                                                               \
                                                  );                                                                                    \
                                             CAL1(Prer1(" N.S       = %g\n",prdF3D(vecteur_normal1,rayon_lumineux_inverse)));           \
                                             CAL1(Prer1(" |N|.|S|   = %g\n",produit_des_modules_de_N_et_S));                            \
                                             Eblock                                                                                     \
                                        ATes                                                                                            \
                                             Bblock                                                                                     \
                                             Eblock                                                                                     \
                                        ETes                                                                                            \
                                                                                                                                        \
                                        Test(IFLE(SOUA(_____cNORMALISE_OZ(Z_approxime(petit_axe_b,grand_axe_a))                         \
                                                      ,loadF_point_valide(Z_Buffer,X,Y)                                                 \
                                                       )                                                                                \
                                                 ,_____lNORMALISE_OZ(EPAISSEUR_DE_L_INTERSECTION)                                       \
                                                  )                                                                                     \
                                             )                                                                                          \
                                        /* Nota : on ecrit ainsi, et non pas :                                                       */ \
                                        /*                                                                                           */ \
                                        /*                  Test(IFLE(SOUA(Z_approxime(petit_axe_b,grand_axe_a)                      */ \
                                        /*                                ,_cDENORMALISE_OZ(loadF_point_valide(Z_Buffer,X,Y))        */ \
                                        /*                                 )                                                         */ \
                                        /*                           ,EPAISSEUR_DE_L_INTERSECTION                                    */ \
                                        /*                            )                                                              */ \
                                        /*                       )                                                                   */ \
                                        /*                                                                                           */ \
                                        /* afin d'alleger le travail du compilateur...                                               */ \
                                             Bblock                                                                                     \
                                             DEFV(Float                                                                                 \
                                                 ,INIT(correction_d_anti_aliasing_aux_intersections                                     \
                                                      ,INTERPOLATION_CUBIQUE(COORDONNEE_BARYCENTRIQUE_MINIMALE                          \
                                                                            ,FZERO                                                      \
                                                                            ,COORDONNEE_BARYCENTRIQUE_MAXIMALE                          \
                                                                            ,FZERO                                                      \
                                                                            ,DIVI(SOUA(_____cNORMALISE_OZ(Z_approxime(petit_axe_b       \
                                                                                                                     ,grand_axe_a       \
                                                                                                                      )                 \
                                                                                                          )                             \
                                                                                      ,loadF_point_valide(Z_Buffer,X,Y)                 \
                                                                                       )                                                \
                                                                                 ,_____lNORMALISE_OZ(EPAISSEUR_DE_L_INTERSECTION)       \
                                                                                  )                                                     \
                                                                             )                                                          \
                                                       )                                                                                \
                                                  );                                                                                    \
                                        /* Lorsque le point a marquer est pratiquement a la meme profondeur que le point precedent,  */ \
                                        /* c'est qu'il y a intersection de deux spheres : on va donc faire la moyenne du niveau a    */ \
                                        /* a marquer et du niveau anterieur...                                                       */ \
                                             Test(IFEQ(correction_d_anti_aliasing_au_bord,COORDONNEE_BARYCENTRIQUE_MAXIMALE))           \
                                                  Bblock                                                                                \
                                                  EGAL(correction_d_anti_aliasing_au_bord                                               \
                                                      ,correction_d_anti_aliasing_aux_intersections                                     \
                                                       );                                                                               \
                                        /* Cas ou l'on est juste en presence d'une intersection...                                   */ \
                                                  Eblock                                                                                \
                                             ATes                                                                                       \
                                                  Bblock                                                                                \
                                                  EGAL(correction_d_anti_aliasing_au_bord                                               \
                                                      ,MIN2(correction_d_anti_aliasing_au_bord                                          \
                                                           ,correction_d_anti_aliasing_aux_intersections                                \
                                                            )                                                                           \
                                                       );                                                                               \
                                        /* Cas ou l'on est en presence simultanement d'un bord et d'une intersection. On notera que  */ \
                                        /* l'on utilise la fonction 'MIN2(...)', car en effet l'utilisation de 'MOYE(...)' faisait   */ \
                                        /* apparaitre des defauts visuels (points sur-lumineux) la ou il y avait une forte disparite */ \
                                        /* entre les deux correctiond ("de bord" et "d'intersection") ; l'utilisation de 'MAX2(...)' */ \
                                        /* ne faisait qu'amplifier ces defauts...                                                    */ \
                                                  Eblock                                                                                \
                                             ETes                                                                                       \
                                             Eblock                                                                                     \
                                        ATes                                                                                            \
                                             Bblock                                                                                     \
                                             Eblock                                                                                     \
                                        ETes                                                                                            \
                                                                                                                                        \
                                        Test(NINCff(correction_d_anti_aliasing_au_bord                                                  \
                                                   ,COORDONNEE_BARYCENTRIQUE_MINIMALE                                                   \
                                                   ,COORDONNEE_BARYCENTRIQUE_MAXIMALE                                                   \
                                                    )                                                                                   \
                                             )                                                                                          \
                                             Bblock                                                                                     \
                                             PRINT_ERREUR("le parametre d'interpolation n'est pas dans [0,1]");                         \
                                             CAL1(Prer1(" parametre d'interpolation = %g\n",correction_d_anti_aliasing_au_bord));       \
                                             Eblock                                                                                     \
                                        ATes                                                                                            \
                                             Bblock                                                                                     \
                                             Eblock                                                                                     \
                                        ETes                                                                                            \
                                                                                                                                        \
                                        niveau_RVB(niveau_ROUGE_du_point,nbR,ncR,iR);                                                   \
                                        niveau_RVB(niveau_VERTE_du_point,nbV,ncV,iV);                                                   \
                                        niveau_RVB(niveau_BLEUE_du_point,nbB,ncB,iB);                                                   \
                                        /* Enfin, calcul du niveau du point courant.                                                 */ \
                                        Eblock                                                                                          \
                                   ATes                                                                                                 \
                                        Bblock                                                                                          \
                                        Eblock                                                                                          \
                                   ETes                                                                                                 \
                                                                                                                                        \
                                   Test(IL_FAUT(randomiser_la_visualisation_des_particules))                                            \
                                        Bblock                                                                                          \
                                        GENERATION_D_UNE_VALEUR_SANS_DEPLACEMENT(distance_aleatoire_au_centre                           \
                                                                                ,MUL2(rayon_interieur_relatif_d_une_particule           \
                                                                                     ,MAX2(petit_axe_b,grand_axe_a)                     \
                                                                                      )                                                 \
                                                                                ,MUL2(rayon_exterieur_relatif_d_une_particule           \
                                                                                     ,MAX2(petit_axe_b,grand_axe_a)                     \
                                                                                      )                                                 \
                                                                                 );                                                     \
                                        /* Calcul d'une valeur aleatoire permettant de determiner si le point courant {X,Y} doit     */ \
                                        /* etre marque. On utilise la fonction 'GENERATION_D_UNE_VALEUR_SANS_DEPLACEMENT(...)' et    */ \
                                        /* non pas 'GENERATION_D_UNE_VALEUR(...)' car en effet les calculs sont effectues ici dans   */ \
                                        /* les coordonnees de visualisation, et en particulier apres projection perspective. Dans    */ \
                                        /* ces conditions, lorsqu'un calcul en stereoscopie est effectuee, il y a peu de chance      */ \
                                        /* pour qu'une meme particule soit materialisee avec le meme nombre de points sur les vues   */ \
                                        /* 'DROITE' et 'GAUCHE'. Dans ces conditions, 'GENERATION_D_UNE_VALEUR(...)' n'est pas       */ \
                                        /* appele le meme nombre de fois pour les images 'DROITE' et 'GAUCHE', et donc les suites    */ \
                                        /* d'evenements pour les deux images seront donc completement differentes, ce qui est        */ \
                                        /* impensable...                                                                             */ \
                                        EGAL(marquer_le_point_courant                                                                   \
                                            ,IFGE(distance_aleatoire_au_centre                                                          \
                                                 ,RdisF2D(FLOT(X),FLOT(Y)                                                               \
                                                         ,ASD1(centre_du_disque,x),ASD1(centre_du_disque,y)                             \
                                                          )                                                                             \
                                                  )                                                                                     \
                                             );                                                                                         \
                                        /* Et on regarde si le point courant est a marquer a l'aide de sa distance au centre et du   */ \
                                        /* nombre aleatoire calcule precedemment...                                                  */ \
                                        Eblock                                                                                          \
                                   ATes                                                                                                 \
                                        Bblock                                                                                          \
                                        Eblock                                                                                          \
                                   ETes                                                                                                 \
                                                                                                                                        \
                                   Test(IL_FAUT(marquer_le_point_courant))                                                              \
                                        /* Nota : on pourrait dire a juste raison que ce test n'est pas tres optimise ; en effet,    */ \
                                        /* il serait plus asticieux de le placer tout en haut de cette sequence, et par exemple      */ \
                                        /* juste apres le test :                                                                     */ \
                                        /*                                                                                           */ \
                                        /*                  Test(IFOU(IZGT(petit_axe_b),IZGT(grand_axe_a)))                          */ \
                                        /*                                                                                           */ \
                                        /* Mais en fait j'ai procede ainsi afin de simplifier la mise en place de cette possibilite. */ \
                                        /*                                                                                           */ \
                                        /* D'autre part, le fait qu'il soit fait systematiquement, sans optimiser (par exemple dans  */ \
                                        /* le cas ou les rayons "interieur" et "exterieur" sont tous deux egaux a 1.0) fait que la   */ \
                                        /* sequence des nombres aleatoires generes (avec tous les autres parametres inchanges) est   */ \
                                        /* est toujours la meme, ce qui fait que la sequence des evenements est elle aussi la meme.  */ \
                                        Bblock                                                                                          \
                                        store_point_ND_RVB(niveau_ROUGE_du_point,niveau_VERTE_du_point,niveau_BLEUE_du_point            \
                                                          ,iR,iV,iB                                                                     \
                                                          ,X,Y                                                                          \
                                                          ,_____cNORMALISE_OZ(Z_approxime(petit_axe_b,grand_axe_a))                     \
                                                          ,TRI_DIMENSIONNEL                                                             \
                                                           );                                                                           \
                                        /* Generation des points de l'ellipsoide, et ce uniquement si la distance aleatoire se situe */ \
                                        /* dans [rayon_interieur_relatif_d_une_particule,rayon_exterieur_relatif_d_une_particule]    */ \
                                        /* (en renormalisant dans [0,1]).                                                            */ \
                                        Eblock                                                                                          \
                                   ATes                                                                                                 \
                                        Bblock                                                                                          \
                                        Eblock                                                                                          \
                                   ETes                                                                                                 \
                                   Eblock                                                                                               \
                              ATes                                                                                                      \
                                   Bblock                                                                                               \
                                   Eblock                                                                                               \
                              ETes                                                                                                      \
                              Eblock                                                                                                    \
                         end_ligneQ(EDoI)                                                                                               \
                         Eblock                                                                                                         \
                    end_colonneQ(EDoI)                                                                                                  \
                    Eblock                                                                                                              \
                                        /* ATTENTION : {X,Y,Z} E [Xmin,Xmax]x[Ymin,Ymax]x[Zmin,Zmax].                                */



Copyright © Jean-François Colonna, 2019-2021.
Copyright © CMAP (Centre de Mathématiques APpliquées) UMR CNRS 7641 / Ecole Polytechnique, 2019-2021.