/*************************************************************************************************************************************/
/* */
/* C A L C U L G E N E R A L D E L ' E N S E M B L E D E J U L I A */
/* S U I V A N T U N E E Q U I P O T E N T I E L L E D E */
/* L ' E N S E M B L E D E M A N D E L B R O T */
/* D A N S L E P L A N C O M P L E X E : */
/* */
/* */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* * * * ** * * * * * ** * */
/* * * * * * * * * * * * * * * * */
/* * * * * * * * * * * * * * */
/* * * * * * * * * * * * * * * * */
/* * * * * * * * * * * * * * * * */
/* * * * * * * * * * * * * * * * * * */
/* * * * * * * * * * * * * * */
/* * * * * * * * * * * * * * * * */
/* * * * * ** * * * * * ** */
/* * * * * * * * * * * * * * * * * * * * * * * */
/* */
/* */
/* ATTENTION : */
/* */
/* Ce programme, avant le 19970206000000, */
/* ne calculait en fait correctement que */
/* des images au format carre ('Std' par */
/* exemple). Il a fallu introduire les */
/* fonction 'CHANGEMENT_HOMOTHETIQUE...(...)' */
/* pour corriger cette anomalie... */
/* */
/* */
/* Author of '$xrc/julia.02$K' : */
/* */
/* Jean-Francois COLONNA (LACTAMME, 1988??????????). */
/* */
/*************************************************************************************************************************************/
/*===================================================================================================================================*/
/*************************************************************************************************************************************/
/* */
/* I N T E R F A C E ' listG ' : */
/* */
/* */
/* :Debut_listG: */
/* :Fin_listG: */
/* */
/*************************************************************************************************************************************/
/*===================================================================================================================================*/
/*************************************************************************************************************************************/
/* */
/* D I R E C T I V E S S P E C I F I Q U E S D E C O M P I L A T I O N : */
/* */
/*************************************************************************************************************************************/
#define GENERER_LES_GET_ARGUMENTS_DE_CONTROLE_DE_L_ARITHMETIQUE_ETENDUE_DES_NOMBRES_FLOTTANTS
/* Introduit le 20070129112458... */
/*===================================================================================================================================*/
/*************************************************************************************************************************************/
/* */
/* F I C H I E R S D ' I N C L U D E S : */
/* */
/*************************************************************************************************************************************/
#include INCLUDES_BASE
#include image_image_CONTOURS_EXT
#include maths_compl_fonct_ITERATIONS_EXT
#include image_image_QUAD_IMAGE_EXT
/*===================================================================================================================================*/
/*************************************************************************************************************************************/
/* */
/* P A R A M E T R E S : */
/* */
/*************************************************************************************************************************************/
#define COMPATIBILITE_20190321 \
FAUX \
/* Permet de proceder a des generations compatibles a celles qui furent effectues */ \
/* anterieurement au 20190321131841. */
#define M_FENETRE_GAUCHE \
PARE(-2.0)
#define M_FENETRE_DROITE \
PARE(0.5)
#define vM_FENETRE_GAUCHE \
CHANGEMENT_HOMOTHETIQUE_D_ABSCISSE_GAUCHE(M_FENETRE_GAUCHE,M_FENETRE_DROITE)
#define vM_FENETRE_DROITE \
CHANGEMENT_HOMOTHETIQUE_D_ABSCISSE_DROITE(M_FENETRE_GAUCHE,M_FENETRE_DROITE)
#define M_FENETRE_GD \
SOUS(vM_FENETRE_DROITE,vM_FENETRE_GAUCHE)
#define M_FENETRE_BAS \
PARE(-1.25)
#define M_FENETRE_HAUT \
PARE(1.25)
#define vM_FENETRE_BAS \
CHANGEMENT_HOMOTHETIQUE_D_ORDONNEE_BAS(M_FENETRE_BAS,M_FENETRE_HAUT)
#define vM_FENETRE_HAUT \
CHANGEMENT_HOMOTHETIQUE_D_ORDONNEE_HAUT(M_FENETRE_BAS,M_FENETRE_HAUT)
#define M_FENETRE_BH \
SOUS(vM_FENETRE_HAUT,vM_FENETRE_BAS)
/* Definition de la fenetre de calcul de l'ensemble de Mandelbrot. */
#define M_NOMBRE_D_ITERATIONS \
QUAR(COULEURS) \
/* Nombre d'iterations demandees pour le calcul de l'ensemble de Mandelbrot. */
#define SEUIL \
GENP(MUL2(FLOT(PRED(PRED(PRED(PRED(PRED(MOIT(GRIS_1))))))) \
,DIVI(FLOT__BLANC,FLOT(M_NOMBRE_D_ITERATIONS)) \
) \
) \
/* Seuil d'extraction du contour, c'est-a-dire numero de l'equipotentielle. */
#define E_DEPART_X \
_____cNORMALISE_OX(COND(IL_FAUT(compatibilite_20190321),I_cHOMOTHETIE_Std_OX(Xmin),Xmin))
#define E_DEPART_Y \
_____cNORMALISE_OY(COND(IL_FAUT(compatibilite_20190321),I_cHOMOTHETIE_Std_OY(Ymin),Ymin))
/* Point de depart de l'extraction de l'equipotentielle. */
/* */
/* Le 20120212101505, les 'I_cHOMOTHETIE_Std_O?(...)'s furent introduits... */
#define NOMBRE_DE_CONTOURS \
HUIT \
/* Nombre de contours interieurs a l'equipotentielle a extraire pour definir */ \
/* le vrai contour que l'on va suivre ; s'il est nul, on prend directement */ \
/* equipotentielle... */
#define C_DEPART_X \
_____cNORMALISE_OX(COND(IL_FAUT(compatibilite_20190321),I_cHOMOTHETIE_Std_OX(Xcentre),Xcentre))
#define C_DEPART_Y \
_____cNORMALISE_OY(COND(IL_FAUT(compatibilite_20190321),I_cHOMOTHETIE_Std_OY(Ycentre),Ycentre))
/* Point de depart de l'extraction de contour. */
/* */
/* Le 20120212101505, les 'I_cHOMOTHETIE_Std_O?(...)'s furent introduits... */
#define CONTOUR \
BLANC \
/* Niveau de marquage du contour... */
#define CALCUL \
ZERO \
/* Lorsque 'sauts_des_calculs' vaut 'CALCUL', l'image courante est */ \
/* generee ; en fait, on ne calcule qu'une image sur 'pas_de_calcul'... */
#define PAS_DE_CALCUL \
PAR0(QUATORZE) \
/* Pour une image calculee, on en saute 'pas_de_calcul'-1 ; ce nombre doit */ \
/* etre pair afin de limiter au maximum les effets de saccades (en marches */ \
/* d'escalier) lors du suivi des obliques du contour. */
#define J_FENETRE_GAUCHE \
PARE(-1.0)
#define J_FENETRE_DROITE \
PARE(1.0)
#define vJ_FENETRE_GAUCHE \
CHANGEMENT_HOMOTHETIQUE_D_ABSCISSE_GAUCHE(J_FENETRE_GAUCHE,J_FENETRE_DROITE)
#define vJ_FENETRE_DROITE \
CHANGEMENT_HOMOTHETIQUE_D_ABSCISSE_DROITE(J_FENETRE_GAUCHE,J_FENETRE_DROITE)
#define J_FENETRE_BAS \
PARE(-1.0)
#define J_FENETRE_HAUT \
PARE(1.0)
#define vJ_FENETRE_BAS \
CHANGEMENT_HOMOTHETIQUE_D_ORDONNEE_BAS(J_FENETRE_BAS,J_FENETRE_HAUT)
#define vJ_FENETRE_HAUT \
CHANGEMENT_HOMOTHETIQUE_D_ORDONNEE_HAUT(J_FENETRE_BAS,J_FENETRE_HAUT)
/* Definition de la fenetre de calcul des ensembles de Julia. */
#define J_NOMBRE_D_ITERATIONS \
COND(IZEQ(NOMBRE_DE_CONTOURS),QUAR(COULEURS),COULEURS) \
/* Nombre d'iterations demandees pour le calcul des ensembles de Julia ; */ \
/* ce nombre varie suivant qu'on est a l'exterieur ('QUAR(COULEURS)') */ \
/* ou bien a l'interieur ('COULEURS'). */
#define VISUALISATION_ARGUMENTS_DE_SORTIE \
FAUX \
/* Faut-il visualiser l'argument de sortie ('VRAI') ou les equipotentielles ('FAUX'). */
#define PREMIERE_TRAJECTOIRE \
SUCC(NOIR) \
/* Premier niveau de marquage de la trajectoire, */
#define DERNIERE_TRAJECTOIRE \
PRED(CONTOUR) \
/* Premier niveau de marquage de la trajectoire, */
#include xci/sequence.01.I"
#redefine DERNIERE_IMAGE \
INFINI \
/* Numero de la derniere image a generer : ce parametre permet de s'arreter en cours de */ \
/* route... */
/*===================================================================================================================================*/
/*************************************************************************************************************************************/
/* */
/* M A C R O S U T I L E S : */
/* */
/*************************************************************************************************************************************/
#define GENERATEUR_REEL \
AXPB(M_FENETRE_GD,ASD1(point_courant_extrait,x),vM_FENETRE_GAUCHE)
#define GENERATEUR_IMAGINAIRE \
AXPB(M_FENETRE_BH,ASD1(point_courant_extrait,y),vM_FENETRE_BAS)
/* Definition du generateur de l'ensemble de Julia. */
#define DEFINE_CONTOUR(logique1,logique2) \
Bblock \
BoIn(niveau,NOIR,SEUIL,I) \
Bblock \
EGAL(ITb1(exterieur,INDX(niveau,NOIR)),logique1); \
EGAL(ITb1(interieur,INDX(niveau,NOIR)),logique2); \
Eblock \
EBoI \
BoIn(niveau,SUCC(SEUIL),BLANC,I) \
Bblock \
EGAL(ITb1(exterieur,INDX(niveau,NOIR)),logique2); \
EGAL(ITb1(interieur,INDX(niveau,NOIR)),logique1); \
Eblock \
EBoI \
Eblock \
/* Definition de l'interieur et de l'exterieur d'un contour. */
/*===================================================================================================================================*/
/*************************************************************************************************************************************/
/* */
/* C A L C U L G E N E R A L D E L ' E N S E M B L E D E J U L I A */
/* S U I V A N T U N E E Q U I P O T E N T I E L L E D E */
/* L ' E N S E M B L E D E M A N D E L B R O T */
/* D A N S L E P L A N C O M P L E X E : */
/* */
/*************************************************************************************************************************************/
BCommande(nombre_d_arguments,arguments)
/*-----------------------------------------------------------------------------------------------------------------------------------*/
Bblock
DEFV(Logical,INIT(compatibilite_20190321,COMPATIBILITE_20190321));
/* Permet de proceder a des generations compatibles a celles qui furent effectues */
/* anterieurement au 20190321131841. */
DEFV(complexe,M_coin_bas_gauche);
/* Definition du point situe en bas a gauche de la fenetre courante, */
DEFV(complexe,M_coin_haut_droite);
/* Definition du point situe en haut a droite de la fenetre courante, */
/* pour le calcul de l'ensemble de Mandelbrot. */
DEFV(Positive,INIT(M_nombre_maximal_d_iterations,M_NOMBRE_D_ITERATIONS));
/* Nombre maximal d'iterations a effectuer pour le calcul de l'ensemble de */
/* Mandelbrot. */
DEFV(Int,INIT(pas_de_calcul,PAS_DE_CALCUL));
/* Permet de ne calculer qu'un ensemble partiel de Mandelbrot sur 'pas_de_calcul'. */
DEFV(Int,INIT(saut_des_calculs,CALCUL));
/* Permet de ne calculer qu'un ensemble partiel de Mandelbrot sur 'pas_de_calcul'. */
DEFV(Logical,INIT(visualisation_arguments_de_sortie,VISUALISATION_ARGUMENTS_DE_SORTIE));
/* Indicateur de choix entre la visualisation du nombre d'iterations ('FAUX'), */
/* et l'argument de sortie ('VRAI'). */
DEFV(complexe,J_coin_bas_gauche);
/* Definition du point situe en bas a gauche de la fenetre courante, */
DEFV(complexe,J_coin_haut_droite);
/* Definition du point situe en haut a droite de la fenetre courante, */
/* pour le calcul de l'ensemble de Julia. */
DEFV(complexe,point_argument);
/* Nombre complexe generateur. */
DEFV(Positive,INIT(J_nombre_maximal_d_iterations,J_NOMBRE_D_ITERATIONS));
/* Nombre maximal d'iterations a effectuer pour le calcul de l'ensemble de Julia. */
DEFV(processus,Pextraction);
/* Processus d'extraction du contour. */
DEFV(Logical,DTb1(exterieur,COULEURS));
/* Definition de l'exterieur, */
DEFV(Logical,DTb1(interieur,COULEURS));
/* Et de l'interieur. */
DEFV(pointF_2D,point_de_depart);
/* Point de depart de l'extraction de contour. */
DEFV(Logical,INIT(fin_de_contour,FAUX));
/* Afin de connaitre le dernier point du contour, mais on n'y est pas encore... */
DEFV(pointF_2D,point_courant_extrait);
/* Point courant extrait du contour dans [0,1]. */
DEFV(genere_p,INIT(niveau_de_marquage_du_contour,CONTOUR));
/* Niveau de marquage du contour extrait. */
DEFV(Logical,INIT(emission_des_points,VRAI));
/* Afin de transmettre les points du contour... */
DEFV(Int,INIT(numero_d_image,PREMIERE_IMAGE_ABSOLUE));
/* Numero de l'image courante (celle-ci n'est pas necessairement generee : voir */
/* le parametre 'PREMIERE_IMAGE'). */
DEFV(CHAR,INIC(POINTERc(nom_imageR),NOM_PIPE));
/* Nom de la sequence a generer. */
DEFV(Int,INIT(nombre_de_chiffres,NOMBRE_DE_CHIFFRES));
/* Nombre de chiffres codant le numero des images de la sequence a generer. */
DEFV(CHAR,INIC(POINTERc(nom_imageRC),NOM_PIPE));
DEFV(CHAR,INIC(POINTERc(nom_imageRE),NOM_PIPE));
DEFV(CHAR,INIC(POINTERc(nom_imageRM),NOM_PIPE));
DEFV(CHAR,INIC(POINTERc(nom_imageRT),NOM_PIPE));
/* Nom des images resultantes. */
DEFV(CHAR,INIT(POINTERc(nom_image),NOM_UNDEF));
/* Nom courant des images. */
/*..............................................................................................................................*/
Cinitialisation(M_coin_bas_gauche,M_FENETRE_GAUCHE,M_FENETRE_BAS);
Cinitialisation(M_coin_haut_droite,M_FENETRE_DROITE,M_FENETRE_HAUT);
/* Definition de la fenetre de calcul. */
GET_ARGUMENTSv(nombre_d_arguments
,BLOC(GET_ARGUMENT_L("compatibilite_20190321=",compatibilite_20190321);
/* Argument introduit le 20190321131841... */
GET_ARGUMENT_C("imageR=""R=",nom_imageR);
GET_ARGUMENT_I("chiffres=",nombre_de_chiffres);
GET_ARGUMENT_C("imageRC=""RC=",nom_imageRC);
GET_ARGUMENT_C("imageRE=""RE=",nom_imageRE);
GET_ARGUMENT_C("imageRM=""RM=",nom_imageRM);
GET_ARGUMENT_C("imageRT=""RT=",nom_imageRT);
GET_ARGUMENT_L("arguments=",visualisation_arguments_de_sortie);
GET_ARGUMENT_I("pas=",pas_de_calcul);
GET_ARGUMENT_F("exposantJ=",Ijulia_dans_C_____exposant);
GET_ARGUMENT_F("exposantM=",Imandelbrot_dans_C_____exposant);
/* Arguments introduits le 20091118122011... */
/* */
/* Le 20100608132121, passage de 'GET_ARGUMENT_I(...)' a 'GET_ARGUMENT_F(...)'. */
GET_ARGUMENT_F("seuilJ=",Ijulia_dans_C_____seuil_du_carre_du_module);
GET_ARGUMENT_F("seuilM=",Imandelbrot_dans_C_____seuil_du_carre_du_module);
/* Arguments introduits le 20091118183752... */
CONTROLE_DE_L_ARITHMETIQUE_ETENDUE_DES_NOMBRES_COMPLEXES;
/* Cette extension a ete introduite le 20070129112458... */
)
);
SET_FILTRAGE(ACTIF);
/* Afin d'acceder aux listes de substitutions... */
MODIFICATION_LISTE_DE_SUBSTITUTION(BLANC,PRED(PRED(BLANC)));
MODIFICATION_LISTE_DE_SUBSTITUTION(PRED(BLANC),PRED(PRED(BLANC)));
/* Afin de reserver le blanc pour le contour et les pointilles... */
SUBSTITUTION(L_SUBSTITUTION_VARIABLE);
CALS(Imandelbrot_dans_C(ImageA1
,ADRESSE(M_coin_bas_gauche),ADRESSE(M_coin_haut_droite)
,M_nombre_maximal_d_iterations
,FAUX
)
);
/* Calcul de l'ensemble de Mandelbrot dont on va extraire une equipotentielle. */
SET_FILTRAGE(INACTIF);
CALi(Iupdate_image(nom_imageRM,ImageA1));
/* Et on stocke l'ensemble de Mandelbrot... */
DEFINE_CONTOUR(VRAI,FAUX);
/* Definition de l'interieur et de l'exterieur du contour... */
CALS(Idelete_image(nom_imageRE));
Test(IFLE(niveau_de_marquage_du_contour,SUCC(SEUIL)))
Bblock
PRINT_ERREUR("les niveaux de gestion des contours sont incoherents");
Eblock
ATes
Bblock
Test(IZNE(NOMBRE_DE_CONTOURS))
Bblock
INITIALISATION_POINT_2D(point_de_depart,E_DEPART_X,E_DEPART_Y);
/* Choix du point de depart de l'extraction de l'equipotentielle. */
CALi(Inoir(ImageA2));
/* Nettoyage de l'image ou mettre les contours interieurs. */
CALS(Iextraction_contour(ImageA2
,ImageA1
,ADRESSE(point_de_depart)
,exterieur,interieur
,niveau_de_marquage_du_contour
,FAUX,NoProcess
)
);
/* Extraction de l'equipotentielle choisie. */
/* */
/* La valeur 'NoProcess' a ete introduite le 20040619185544... */
CALi(Istore_image(nom_imageRE,ImageA2));
/* Et on stocke l'equipotentielle... */
CALS(Imove(ImageA1,ImageA2));
INITIALISATION_POINT_2D(point_de_depart,C_DEPART_X,C_DEPART_Y);
/* Choix du point de depart de l'extraction de contour. */
Repe(NOMBRE_DE_CONTOURS)
Bblock
CALi(Inoir(ImageA2));
/* Nettoyage de l'image ou mettre les contours interieurs. */
CALS(Iextraction_contour(ImageA2
,ImageA1
,ADRESSE(point_de_depart)
,exterieur,interieur
,niveau_de_marquage_du_contour
,FAUX,NoProcess
)
);
/* Extraction du contour courant interieur a l'equipotentielle. */
/* */
/* La valeur 'NoProcess' a ete introduite le 20040619185544... */
CALS(Imove(ImageA1,ImageA2));
/* De facon a extraire le contour interieur du contour courant... */
Eblock
ERep
Eblock
ATes
Bblock
Eblock
ETes
Eblock
ETes
CALi(Inoir(Image_VERTE));
/* Nettoyage du futur contour pour le processus 'Pextraction', et du */
/* marquage des points ou l'on calcule l'ensemble partiel de Mandelbrot pour le */
/* processus courant (le "pere")... */
iPARALLELE(BLOC(INITIALISATION_POINT_2D(point_de_depart,E_DEPART_X,E_DEPART_Y);
/* Choix du point de depart de l'extraction de contour. */
CALS(Iextraction_contour(Image_VERTE
,ImageA1
,ADRESSE(point_de_depart)
,exterieur,interieur
,niveau_de_marquage_du_contour
,emission_des_points
,ADRESSE(Pextraction)
)
);
/* La valeur 'NoProcess' a ete introduite le 20040619185544... */
CALi(Iupdate_image(nom_imageRC,Image_VERTE));
/* Et on stocke le contour... */
)
,Pextraction
);
/* Envoi en parallele de l'extraction du contour, c'est-a-dire de */
/* l'equipotentielle numero 'SEUIL'. */
Cinitialisation(J_coin_bas_gauche,J_FENETRE_GAUCHE,J_FENETRE_BAS);
Cinitialisation(J_coin_haut_droite,J_FENETRE_DROITE,J_FENETRE_HAUT);
/* Definition de la fenetre de calcul de l'ensemble de Julia. */
Tant(EST_FAUX(fin_de_contour))
Bblock
RECEIVE_F(Pextraction,ASD1(point_courant_extrait,x));
RECEIVE_F(Pextraction,ASD1(point_courant_extrait,y));
/* Recuperation du point courant du contour, */
RECEIVE_L(Pextraction,fin_de_contour);
/* Et de l'indicateur de fin... */
Test(IFOU(IFEQ(saut_des_calculs,CALCUL)
,EST_VRAI(fin_de_contour)
)
)
Bblock
/* On ne fait les calculs que lorsque 'saut_des_calculs' est nul, ou */
/* bien pour le dernier point (afin de "refermer" le contour). */
Test(IFINff(numero_d_image,PREMIERE_IMAGE,DERNIERE_IMAGE))
/* Afin de se positionner dans la sequence... */
Bblock
gVARIABLES_RELATIVES_A_LA_NECESSITE_D_HOMOTHETIE(VRAI);
/* Introduit le 20091126090519 car, en effet, il manquait en notant que la valeur 'VRAI' */
/* assure la compatibilite anterieure... */
Cinitialisation(point_argument
,GENERATEUR_REEL
,GENERATEUR_IMAGINAIRE
);
CALS(Ijulia_dans_C(ImageR
,ADRESSE(J_coin_bas_gauche),ADRESSE(J_coin_haut_droite)
,ADRESSE(point_argument)
,J_nombre_maximal_d_iterations
,visualisation_arguments_de_sortie
)
);
EGAL(nom_image,chain_Aconcaten2_sauf_nom_pipe(nom_imageR,chain_numero(numero_d_image,nombre_de_chiffres)));
CALi(Iupdate_image(nom_image,ImageR));
CALZ_FreCC(nom_image);
/* Et on stocke l'image... */
Eblock
ATes
Bblock
Eblock
ETes
store_point(MODU(numero_d_image,PREMIERE_TRAJECTOIRE,DERNIERE_TRAJECTOIRE)
,Image_VERTE
,_cDENORMALISE_OX(ASD1(point_courant_extrait,x)),_cDENORMALISE_OY(ASD1(point_courant_extrait,y))
,FVARIABLE
);
/* Et marquage du point ou a lieu le calcul avec un niveau fonction */
/* du numero de l'image ; cette mise a jour a lieu meme si les calculs */
/* precedents ne sont pas effectues afin que l'image 'nom_imageRT' */
/* soit toujours correcte, meme lorsque l'on fait une reprise... */
INCR(numero_d_image,I);
/* Numero de la prochaine image a generer. */
Eblock
ATes
Bblock
Eblock
ETes
EGAL(saut_des_calculs
,MODU(SUCC(saut_des_calculs)
,CALCUL
,PRED(INTE(DIVI(FLOT(pas_de_calcul)
,MAX2(DIVI(FLOT(dimX_BASE),FLOT(dimX)),DIVI(FLOT(dimY_BASE),FLOT(dimY)))
)
)
)
)
);
/* Afin de determiner le point suivant de facon "homothetique", c'est-a-dire de facon a ce */
/* que le nombre de points extraits soit a peu pres independant de la taille de l'image... */
Eblock
ETan
CALi(Iupdate_image(nom_imageRT,Image_VERTE));
/* Et on stocke la trajectoire... */
RETU_Commande;
Eblock
ECommande