////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////
//// ENSEMBLE DE MANDELBROT ET DE JULIA
////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
	
	xdel(winsid())
	tohome
	clear
	clc
	
	global Fractale
	
////////////////////////////////////////////////////////////////////////////////
//
//	Initialisation des paramètres
//
////////////////////////////////////////////////////////////////////////////////
	
	stacksize("max");
	
	
	Fractale.Fonction = 'Quadratique';		// Fonction d'itération par défaut
	Fractale.Algorithme = 'Affixes';		// Algorithme
	//Fractale.Algorithme = 'Indices';		// Algorithme
	
	Fractale.Iterations = 100;				// Nombre d'itérations par défaut
	Fractale.Dimension = 400;				// Dimension de la matrice des affixes par défaut
	
	Fractale.IterationsF = 100;				// Nombre d'itérations pour le calcul de la frontière de Julia
	//Fractale.Points = 720;				// Nombre de points de départ pour le calcul de la frontière de Julia
	Fractale.Points = 1440;					// Nombre de points de départ pour le calcul de la frontière de Julia
	//Fractale.Pause = 100;					// Intervalle entre deux itérations de la fonction réciproque
	Fractale.Pause = 50;					// Intervalle entre deux itérations de la fonction réciproque
	
	
	Fractale.NomFichier = '';
	
	Fractale.NomFigure = "Ensemble de Mandelbrot";
	Fractale.NomFigureJ = "Ensemble de Julia";
	Fractale.NomFigureF = "Adhérence de  l''ensemble de Julia";
	
	Fractale.Labels = ['z -> z^2 + c'];
	Fractale.Labels = [Fractale.Labels; 'z -> z^3 + c'];
	Fractale.Labels = [Fractale.Labels; 'z -> z^4 + c'];
	Fractale.Labels = [Fractale.Labels; 'z -> z^5 + c'];
	Fractale.Labels = [Fractale.Labels; 'z -> c.z.(1- z)'];
	Fractale.Labels = [Fractale.Labels; 'z -> z^3 - z + c'];
	Fractale.Labels = [Fractale.Labels; 'z -> 1/2.(z + 1/z) + c'];
	Fractale.Labels = [Fractale.Labels; 'z -> z^2 + 1/z^2 + c'];
	Fractale.Labels = [Fractale.Labels; 'z -> c.sin(z)'];
	Fractale.Labels = [Fractale.Labels; 'z -> c.cos(z)'];
	Fractale.Labels = [Fractale.Labels; 'z -> c.tan(z)'];
	Fractale.Labels = [Fractale.Labels; 'z -> c.sh(z)'];
	Fractale.Labels = [Fractale.Labels; 'z -> c.ch(z)'];
	Fractale.Labels = [Fractale.Labels; 'z -> c.th(z)'];
	Fractale.Labels = [Fractale.Labels; 'z -> c.exp(z)'];
	Fractale.Labels = [Fractale.Labels; 'z -> c.ln(z)'];
	Fractale.Labels = [Fractale.Labels; 'z -> z^z + c'];
	
	Fractale.CouleurFond = [0.9 0.9 0.9];
	Fractale.Couleurs = 1000;	
	

////////////////////////////////////////////////////////////////////////////////
//
//   Actualisation des paramètres
//
////////////////////////////////////////////////////////////////////////////////

function actualiser()
	global Fractale
	
	select Fractale.Fonction
	case "Quadratique" then
		Fractale.Texte = [' de la fonction z -> z^2'];
		Fractale.NomFichier = '2';
		Fractale.Xmin = - 2;   Fractale.Xmax = 1;
		Fractale.Ymin = - 1.5; Fractale.Ymax = 1.5;
	case "Cubique" then
		Fractale.Texte = [' de la fonction z -> z^3'];
		Fractale.NomFichier = '3';
		Fractale.Xmin = - 1.2; Fractale.Xmax = 1.2;
		Fractale.Ymin = - 1.5; Fractale.Ymax = 1.5;
	case "Quartique" then
		Fractale.Texte = [' de la fonction z -> z^4'];
		Fractale.NomFichier = '4';
		Fractale.Xmin = - 1.2; Fractale.Xmax = 1.2;
		Fractale.Ymin = - 1.5; Fractale.Ymax = 1.5;
	case "Quinte" then
		Fractale.Texte = [' de la fonction z -> z^5'];
		Fractale.NomFichier = '5';
		Fractale.Xmin = - 1.2; Fractale.Xmax = 1.2; 
		Fractale.Ymin = - 1.5; Fractale.Ymax = 1.5;
	case "Logistique" then
		Fractale.Texte = [' pour la suite logistique'];
		Fractale.NomFichier = 'Logistique';
		Fractale.Xmin = - 1.2; Fractale.Xmax = 1.2;
		Fractale.Ymin = - 1.2; Fractale.Ymax = 1.2;
	case "Cardan" then
		Fractale.Texte = [' pour la suite de Cardan'];
		Fractale.NomFichier = 'Cardan';
		Fractale.Xmin = - 1.2; Fractale.Xmax = 1.2;
		Fractale.Ymin = - 1.2; Fractale.Ymax = 1.2;
	case "Hénon" then
		Fractale.Texte = [' pour la suite de Hénon'];
		Fractale.NomFichier = 'Hénon';
		Fractale.Xmin = - 2;   Fractale.Xmax = 1;
		Fractale.Ymin = - 1.5; Fractale.Ymax = 1.5;
	case "Rationnel" then
		Fractale.Texte = [' pour une suite rationnelle'];
		Fractale.NomFichier = 'Rationnelle';
		Fractale.Xmin = - 1.2; Fractale.Xmax = 1.2;
		Fractale.Ymin = - 1.5; Fractale.Ymax = 1.5;
	case "Sinus" then
		Fractale.Texte = [' de la fonction sinus'];
		Fractale.NomFichier = 'Sin';
		Fractale.Xmin = - 4;   Fractale.Xmax = 4;
		Fractale.Ymin = - 2;   Fractale.Ymax = 2;
	case "Cosinus" then
		Fractale.Texte = [' de la fonction cosinus'];
		Fractale.NomFichier = 'Cos';
		Fractale.Xmin = - 4;   Fractale.Xmax = 4;
		Fractale.Ymin = - 2;   Fractale.Ymax = 2;
	case "Tangente" then
		Fractale.Texte = [' de la fonction tangente'];
		Fractale.NomFichier = 'Tan';
		Fractale.Xmin = - 2;   Fractale.Xmax = 2;
		Fractale.Ymin = - 2;   Fractale.Ymax = 2;
	case "SinusHyperbolique" then
		Fractale.Texte = [' de la fonction sinus hyperbolique'];
		Fractale.NomFichier = 'Ch';
		Fractale.Xmin = - 2;   Fractale.Xmax = 1;
		Fractale.Ymin = - 1.5; Fractale.Ymax = 1.5;
	case "CosinusHyperbolique" then
		Fractale.Texte = [' de la fonction cosinus hyperbolique'];
		Fractale.NomFichier = 'Sh';
		Fractale.Xmin = - 2;   Fractale.Xmax = 1;
		Fractale.Ymin = - 1.5; Fractale.Ymax = 1.5;
	case "TangenteHyperbolique"	then
		Fractale.Texte = [' de la fonction tangente hyperbolique'];
		Fractale.NomFichier = 'Th';
		Fractale.Xmin = - 2;   Fractale.Xmax = 1;
		Fractale.Ymin = - 1.5; Fractale.Ymax = 1.5
	case "Exponentielle" then
		Fractale.Texte = [' de la fonction exponentielle'];
		Fractale.NomFichier = 'Exp';
		Fractale.Xmin = - 2;   Fractale.Xmax = 1;
		Fractale.Ymin = - 1.5; Fractale.Ymax = 1.5;
	case "Logarithme" then
		Fractale.Texte = [' de la fonction logarithme'];
		Fractale.NomFichier = 'Ln';
		Fractale.Xmin = - 2;   Fractale.Xmax = 1;
		Fractale.Ymin = - 1.5; Fractale.Ymax = 1.5;
	case "Autopuissance" then
		Fractale.Texte = [' de la fonction z -> z^z'];
		Fractale.NomFichier = 'zZ';
		Fractale.Xmin = - 2;   Fractale.Xmax = 1;
		Fractale.Ymin = - 1.5; Fractale.Ymax = 1.5;
	else
		Fractale.Texte = [' d''une fonction inconnue'];
		Fractale.NomFichier = 'Inconnue';
		Fractale.Xmin = - 2;   Fractale.Xmax = 1;
		Fractale.Ymin = - 1.5; Fractale.Ymax = 1.5;
	end
	
	Fractale.XminJ = -1.3;
	Fractale.XmaxJ = 1.3;
	Fractale.YminJ = - 1.3;
	Fractale.YmaxJ = 1.3;
	
	if 0
		Fractale.XminJ = 0.2675;
		Fractale.XmaxJ = 0.2685;
		Fractale.YminJ = 0.591;
		Fractale.YmaxJ = 0.592;
	end
	
	if 0
		select Fractale.Fonction 
		case "Quadratique"			then c = [-1.3 + %i*0.1; 0.27334 - %i*0.00742; 0.1103103 - %i*0.67037; - 0.488679 - %i*0.56790; - 0.561321 + %i*0.64100; - 0.745429 + %i*0.11308];
		case "Cubique"				then c = - 0.5 + %i*0.13;
		
		case "Sinus"				then c = [- 0.01; 0; %i*0.1; %i*0.4];
		case "SinusHyperbolique"	then c = [- 0.01; 0; %i*0.1; %i*0.4];
		
		case "Exponentielle"		then c = [- 0.01; 0; %i*0.1; %i*0.4];
		case "Autopuissance"		then c = - 0.01;
		end
		
	end
endfunction

////////////////////////////////////////////////////////////////////////////////
//
//   Matrices initiales des affixes
//
////////////////////////////////////////////////////////////////////////////////

function C0 = initialiser_C()
	c0x = linspace(Fractale.Xmin, Fractale.Xmax, Fractale.Dimension);
	c0y = linspace(Fractale.Ymin, Fractale.Ymax, Fractale.Dimension);
	
	[C0X, C0Y] = meshgrid(c0x, c0y);
	
	C0 = C0X + %i*C0Y;
endfunction
function Z0 = initialiser_Z()
	x0 = linspace(Fractale.XminJ, Fractale.XmaxJ, Fractale.Dimension);
	y0 = linspace(Fractale.YminJ, Fractale.YmaxJ, Fractale.Dimension);
	
	[X0, Y0] = meshgrid(x0, y0);
	
	Z0 = X0 + %i*Y0;
endfunction

////////////////////////////////////////////////////////////////////////////////
//
//   Informations dans la console
//
////////////////////////////////////////////////////////////////////////////////

function informer(Action)
	global Fractale
	
	select Action
	case "Mandelbrot"		then mprintf(['\tTrace de l''ensemble de Mandelbrot' + Fractale.Texte + '\n'])
	case "Julia"			then mprintf(['\tSélection d''une affixe pour tracer son ensemble de Julia\n'])
	case "JuliaFontière"	then mprintf(['\tSélection d''une affixe pour tracer la frontière de son ensemble de Julia\n'])
	end
endfunction

////////////////////////////////////////////////////////////////////////////////
//
//   Rafraichissement de la figure
//
////////////////////////////////////////////////////////////////////////////////

function rafraichir()
	global Fractale
	
	objet_information = get("infoBandeFonction");
	
	objet_information.String = "Ensemble de Mandelbrot" + Fractale.Texte;
	
	objet_information = get("infoBandeTaille");
	
	objet_information.String = string(Fractale.Dimension) + " x " + string(Fractale.Dimension) + " points | " + string(Fractale.Iterations) + " itérations";
endfunction

///////////////////////////////////////////////////////////////////////////////
//
//	Enregistrement de la figure
//
///////////////////////////////////////////////////////////////////////////////

function enregistrer(Extension)
	global Fractale
	
	Date = getdate();
	Horodatage = ['_' + string(Date(1)) + '-' + string(Date(2)) + '-' + string(Date(4)) + '_' + string(Date(7)) + '-' + string(Date(8)) + '-' + string(Date(9))];
	
	select Extension
	case "PNG"	then xs2png(interface, "Mandelbrot" + Fractale.NomFichier + Horodatage);
	case "GIF"	then xs2gif(interface, "Mandelbrot" + Fractale.NomFichier + Horodatage);
	case "JPG"	then xs2jpg(interface, "Mandelbrot" + Fractale.NomFichier + Horodatage);
	case "PDF"	then xs2pdf(interface, "Mandelbrot" + Fractale.NomFichier + Horodatage);
	end
endfunction	

////////////////////////////////////////////////////////////////////////////////
//
//   Fonction à itérer
//
////////////////////////////////////////////////////////////////////////////////

function Z1 = f(Z, C)
	global Fractale
	
	select Fractale.Fonction
	case "Quadratique"			then Z1 = Z.^2 + C;
	case "Cubique"				then Z1 = Z.^3 + C;
	case "Quartique"			then Z1 = Z.^4 + C;
	case "Quinte"				then Z1 = Z.^5 + C;
	
	case "Logistique"			then Z1 = C.*Z.*(1 - Z);
	case "Cardan"				then Z1 = Z.^3 - Z + C;
	
	case "Hénon"				then Z1 = 1/2*(Z + 1 ./Z) + C;
	case "Rationnelle"			then Z1 = Z.^2 + 1 ./Z.^2 + C;
	
	case "Sinus"				then Z1 = C.*sin(Z);
	case "Cosinus"				then Z1 = C.*cos(Z);
	case "Tangente"				then Z1 = C.*tan(Z);
	
	case "SinusHyperbolique"	then Z1 = C.*sinh(Z);
	case "CosinusHyperbolique"	then Z1 = C.*cosh(Z);
	case "TangenteHyperbolique"	then Z1 = C.*tan(Z);
	
	case "Exponentielle"		then Z1 = C.*exp(Z);
	case "Logarithme"			then Z1 = C.*log(Z);
	case "Autopuissance"		then Z1 = Z.^Z + C;
	end
endfunction

////////////////////////////////////////////////////////////////////////////////
//
//   Fonction réciproque
//
////////////////////////////////////////////////////////////////////////////////

function Z1 = fReciproque(Z, c)
	global Fractale
	
	Epsilon = sign(rand(size(Z, 1), size(Z, 2)) - 0.5);
	Zeros1 = zeros(size(Z, 1), size(Z, 2));
	
	select Fractale.Fonction
	case "Quadratique"			then Z1 = Epsilon.*sqrt(Z - c);
	case "Cubique"				then Z1 = Zeros1;
	case "Quartique"			then Z1 = Zeros1;
	case "Quinte"				then Z1 = Zeros1;
	
	case "Logistique"			then Z1 = 1/2 + Epsilon.*sqrt(1/4 - Z/c);
	case "Cardan"				then Z1 = Zeros1;
	
	case "Hénon"				then Z1 = Z - C + Epsilon*sqrt((Z - C).^2 - 1);
	case "Rationnelle"			then Z1 = Zeros1;
	
	case "Sinus"				then Z1 = Epsilon.*asin(Z/C);
	case "Cosinus"				then Z1 = Epsilon.*acos(Z/C);
	case "Tangente"				then Z1 = Epsilon.*tan(Z/C);
	
	case "SinusHyperbolique"	then Z1 = Epsilon.*asinh(Z/C);
	case "CosinusHyperbolique"	then Z1 = Epsilon.*acosh(Z/C);
	case "TangenteHyperbolique"	then Z1 = Epsilon.*atan(Z/C);
	
	case "Exponentielle"		then Z1 = log(Z/C);
	case "Logarithme"			then Z1 = exp(Z/C);
	case "Autopuissance"		then Z1 = Zeros1;
	end
endfunction

////////////////////////////////////////////////////////////////////////////////
//
//	La matrice-ligne J stocke les indices des points dans l'ensemble de Mandelbrot.
//	Au démarrage J contient les indices de 1 à Fractale.Dimension*Fractale.Dimension, 
//	ce qui signifie que tous les points sont présumés dans l'ensemble.
//
//	A chaque itération les points dont la suite aura dépassé le module critique  
//	seront otés en affectant l'entrée correspondant de J à zéro.
//	Les indices des points dont la suite n'a pas dépassé le module critique 
//	sont calculés avec l'assertion Liste = J(J>0)
//
//	Au cours du déroulement de l'algorithme le nombre de points diminuera 
//	comme la taille de la matrice Liste.
//	Les calculs n'étant effectués que sur les entrées définies dans Liste, 
//	chaque itération sera donc plus rapide que la précédente.
//
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
//
//	Calcul de la grille des indices
//
////////////////////////////////////////////////////////////////////////////////	

function R = indices(C)
	global Fractale
	
	// Matrices des affixes Z dans l'expression Z = Z²+C
	Z = zeros(Fractale.Dimension, Fractale.Dimension);
	
	// Matrice des modules
	W = zeros(Fractale.Dimension, Fractale.Dimension);
	
	// Matrice des indices k pour lesquels le module excède 2
	R = - ones(Fractale.Dimension, Fractale.Dimension);
	
	// Indices des suites n'ayant pas divergé
	J = 1:Fractale.Dimension*Fractale.Dimension;
	
	// Itération
	for k = 0:Fractale.Iterations
		// Actualise la matrice des affixes pour les suites n'ayant pas divergé
		L = J(J > 0);
		Z(L) = f(Z(L), C(L));
		
		// Détermine les suites ayant divergé (module de Z(k)supérieur à 2)
		W(L) = abs(Z(L));
		M = find(W(L)>2);
		R(L(M)) = k;
		J(L(M)) = 0;
		
		// Indicateur de progression
		mprintf(['\tNombre d''iterations effectuees: %d/%d\n'], k, Fractale.Iterations)
	end
	// R = R';
endfunction

////////////////////////////////////////////////////////////////////////////////
//
//	Calcul de la grille des affixes
//
////////////////////////////////////////////////////////////////////////////////

function Z = affixes(C)
	J = 1:Fractale.Dimension*Fractale.Dimension;
	//Z = zeros(Fractale.Dimension, Fractale.Dimension);
	Z = C;
	
	for k = 1:Fractale.Iterations
		// Ecrètement des affixes ( accélération du calcul )
		Liste = J(J > 0);
		
		// Traceur
		//disp(size(Z)); disp(size(C));
		
		// Calcul des nouvelles affixes
		Z(Liste) = f(Z(Liste), C(Liste));
		
		// Ecrètement des affixes ( accélération du calcul )
		M = find(abs(Z(Liste)) > 2);
		J(Liste(M)) = 0;
		
		// Indicateur de progression
		//mprintf(['\tNombre d''iterations effectuees: %d/%d\n'], k, Fractale.Iterations)
		waitbar(k/Fractale.Iterations, bandeau_progression);
	end
endfunction
function Z = affixes_Julia(C)
	J = 1:Fractale.Dimension*Fractale.Dimension;
	Z = Z0;
	
	for k = 1:Fractale.Iterations
		// Ecrètement des affixes ( accélération du calcul )
		Liste = J(J > 0);
		
		// Calcul des nouvelles affixes
		Z(Liste) = f(Z(Liste), C);
		
		// Ecrètement des affixes ( accélération du calcul )
		M = find(abs(Z(Liste)) > 2);
		J(Liste(M)) = 0;
		
		// Indicateur de progression
		waitbar(k/Fractale.Iterations, bandeau_progression);
	end
endfunction

///////////////////////////////////////////////////////////////////////////////
//
//	Tracé de l'ensemble de Mandelbrot
//
///////////////////////////////////////////////////////////////////////////////

function tracer_Mandelbrot()
	global Fractale
	
	actualiser()
	informer("Mandelbrot")
	
	// Calcul de la matrice d'affixes
	C0 = initialiser_C();
	
	bandeau_progression = waitbar("Calcul des affixes");
	
	tic();	
	
	if (Fractale.Algorithme == "Affixes"), Z = affixes(C0); end
	if (Fractale.Algorithme == "Indices"), R = indices(C0); end
	
	Fractale.DureeCalcul = toc();
	
	// mprintf("\t\n");
	// mprintf("\tTemps écoulé = %f (s)\n", Fractale.DureeCalcul);
	
	// Fractale.PPS = floor(Fractale.Dimension*Fractale.Dimension/Fractale.DureeCalcul);
	// mprintf("\t%d pixels à la seconde\n", Fractale.PPS);
	
	close(bandeau_progression);
	
	// Sauvegarde de la matrice calculée
	save("Mandelbrot" + Fractale.NomFichier + ".sod", 'C0', 'Z')
	
	// Tracé de l'ensemble de Mandelbrot
	objet_mandelbrot = get("traceMatrice");
	
	objet_mandelbrot.children(1).data = abs(Z);
endfunction
function tracer_Mandelbrot_contour()
	global Fractale
	
	figure()
	xVect = linspace(Fractale.Xmin, Fractale.Xmax, Fractale.Dimension);
	yVect = linspace(Fractale.Ymin, Fractale.Ymax, Fractale.Dimension);
	contour2d(xVect, yVect, abs(Z), 5, rect = [1, 1, Fractale.Dimension, Fractale.Dimension])
endfunction

///////////////////////////////////////////////////////////////////////////////
//
//	Tracé de l'ensemble de Julia
//
///////////////////////////////////////////////////////////////////////////////
//  delete
//  is_handle_valid 

function tracer_Julia()
	global Fractale
	
	actualiser()
	informer("Julia")
	
	// Nettoyage des sélections précedentes
	//a = get("traceCourbe");
	//p = get("pointJulia");
	//if is_handle_valid(p)
	//	delete(p)
	//end
	
	// Sélection de l'affixe de l'ensemble de Julia
	a = get("traceCourbe");
	[ibutton, xcoord, ycoord, iwin, cbmenu] = xclick()
	point_selection = plot(xcoord, ycoord, 'r+')
	point_selection.tag = "pointJulia";
	
	cX = Fractale.Xmin + (Fractale.Xmax - Fractale.Xmin)*(xcoord - 1)/(Fractale.Dimension);
	cY = Fractale.Ymin + (Fractale.Ymax - Fractale.Ymin)*(ycoord - 1)/(Fractale.Dimension);
	c = cX+ %i*cY;
	
	actualiser()
	mprintf(['\tTrace de l''ensemble de Julia pour l''affixe ' + string(cX) + ' + i*' + string(cY) + '\n'])
	
	// Calcul de la matrice d'affixes
	Z0 = initialiser_Z();
	
	bandeau_progression = waitbar("Calcul des affixes");
	Z = affixes_Julia(c);
	close(bandeau_progression);
	
	// Sauvegarde de la matrice calculée
	save("Julia" + Fractale.NomFichier + ".sod", 'Z0', 'Z')
	
	// Tracé de l'ensemble de Julia
	//interface_julia = figure('figure_position', [0, 0])
	interface_julia = figure()
	interface_julia.Figure_size = [700, 700];
	interface_julia.Auto_resize = 'on';
	interface_julia.Figure_name = Fractale.NomFigureJ;
	interface_julia.Backgroundcolor = Fractale.CouleurFond;
	
	axes_julia = newaxes();
	
	//axes_julia.axes_bounds = [0, 0, 0.75, 0.75];
	axes_julia.axes_bounds = [0, 0, 1, 1];
	axes_julia.margins = [0, 0, 0, 0];
	
	axes_julia.axes_visible = "off";
	axes_julia.x_location = "top";
	axes_julia.y_location = "left";
	axes_julia.box = "off";
	axes_julia.isoview = "on";
	axes_julia.data_bounds = [1, 1; Fractale.Dimension, Fractale.Dimension];
	
	axes_julia.tag = "traceMatriceJulia";
	
	Matplot(abs(Z), "021")
endfunction

///////////////////////////////////////////////////////////////////////////////
//
//	Tracé de la frontière de l'ensemble de Julia
//
///////////////////////////////////////////////////////////////////////////////

function tracer_Julia_frontiere()
	global Fractale
	
	actualiser()
	informer("Julia-Frontière")
	
	// Sélection de l'affixe de l'ensemble de Julia
	a = get("traceCourbe");
	[ibutton, xcoord, ycoord, iwin, cbmenu] = xclick()
	plot(xcoord, ycoord, 'r+')
	
	cX = Fractale.Xmin + (Fractale.Xmax - Fractale.Xmin)*(xcoord - 1)/(Fractale.Dimension);
	cY = Fractale.Ymin + (Fractale.Ymax - Fractale.Ymin)*(ycoord - 1)/(Fractale.Dimension);
	c = cX + %i*cY;
	
	actualiser()
	mprintf(['\tTrace de l''ensemble de Julia pour l''affixe ' + string(cX) + ' + i*' + string(cY) + '\n'])
	
	// Création de la figure secondaire pour le tracé de la frontière de l'ensemble de Julia
	//interface_juliaF = figure('figure_position', [0, 0])
	interface_juliaF = figure()
	interface_juliaF.Figure_size = [700, 700];
	interface_juliaF.Auto_resize = 'on';
	interface_juliaF.Figure_name = Fractale.NomFigureF;
	interface_juliaF.Backgroundcolor = Fractale.CouleurFond;
	
	axes_julia = newaxes()
	axes_julia.data_bounds = [Fractale.XminJ, Fractale.YminJ; Fractale.XmaxJ, Fractale.YmaxJ];
	axes_julia.tag = "traceFrontiereJulia";
	
	m = 1:Fractale.Points;
	Z0 = exp(%i*%pi*m/360);
	plot(real(Z0), imag(Z0), 'r.')
	
	Z = Z0;
	plot(real(Z), imag(Z), 'b.')
	
	axes_julia.children(1).children(1).mark_size = 1;
	axes_julia.children(2).children(1).mark_size = 1;
	
	// Itérations de la fonction réciproque
	for i = 1:Fractale.IterationsF
		Z = fReciproque(Z, c);
		
		objet_julia = get("traceFrontiereJulia");
		
		objet_julia.children(1).children(1).data(:, 1) = real(Z).';
		objet_julia.children(1).children(1).data(:, 2) = imag(Z).';
		
		sleep(Fractale.Pause)
	end
endfunction

///////////////////////////////////////////////////////////////////////////////
//
//	Initialisation de l'interface
//	figure > axes > tracé (courbe(s), matrice ...)
//
///////////////////////////////////////////////////////////////////////////////
	
	actualiser()
	
//	Création de la figure
	interface = figure('figure_position', [0, 0])
	interface.Figure_size = [700, 700];
	interface.Auto_resize = 'on';
	interface.Figure_name = Fractale.NomFigure;
	interface.Backgroundcolor = Fractale.CouleurFond;
	
	delmenu(interface.figure_id, gettext('File'))
	delmenu(interface.figure_id, gettext('?'))
	delmenu(interface.figure_id, gettext('Tools'))
	toolbar(interface.figure_id, 'off')
	
//	Menu de sélection de la fonction d'itération
	mF = uimenu(interface, 'label', 'Fonction');
	
	mFZ2 = uimenu(mF, 'label', Fractale.Labels( 1, 1), 'callback', "Fractale.Fonction = ''Quadratique'';          actualiser(); rafraichir()")
	mFZ3 = uimenu(mF, 'label', Fractale.Labels( 2, 1), 'callback', "Fractale.Fonction = ''Cubique'';              actualiser(); rafraichir()")
	mFZ4 = uimenu(mF, 'label', Fractale.Labels( 3, 1), 'callback', "Fractale.Fonction = ''Quartique'';            actualiser(); rafraichir()")
	mFZ5 = uimenu(mF, 'label', Fractale.Labels( 4, 1), 'callback', "Fractale.Fonction = ''Quinte'';               actualiser(); rafraichir()")
	
	mF01 = uimenu(mF, 'label', ' ')
	
	mFLo = uimenu(mF, 'label', Fractale.Labels(5, 1), 'callback', "Fractale.Fonction = ''Logistique'';            actualiser(); rafraichir()")
	mFCa = uimenu(mF, 'label', Fractale.Labels(6, 1), 'callback', "Fractale.Fonction = ''Cardan'';                actualiser(); rafraichir()")
	
	mF02 = uimenu(mF, 'label', ' ')
	
	mFHe = uimenu(mF, 'label', Fractale.Labels( 7, 1), 'callback', "Fractale.Fonction = ''Hénon'';                actualiser(); rafraichir()")
	mFRa = uimenu(mF, 'label', Fractale.Labels( 8, 1), 'callback', "Fractale.Fonction = ''Rationnelle'';          actualiser(); rafraichir()")
	
	mF03 = uimenu(mF, 'label', ' ')
	
	mFS =  uimenu(mF, 'label', Fractale.Labels( 9, 1), 'callback', "Fractale.Fonction = ''Sinus'';                actualiser(); rafraichir()")
	mFC =  uimenu(mF, 'label', Fractale.Labels(10, 1), 'callback', "Fractale.Fonction = ''Cosinus'';              actualiser(); rafraichir()")
	mFT =  uimenu(mF, 'label', Fractale.Labels(11, 1), 'callback', "Fractale.Fonction = ''Tangente'';             actualiser(); rafraichir()")
	
	mF04 = uimenu(mF, 'label', ' ')
	
	mFSh = uimenu(mF, 'label', Fractale.Labels(12, 1), 'callback', "Fractale.Fonction = ''SinusHyperbolique'';    actualiser(); rafraichir()")
	mFCh = uimenu(mF, 'label', Fractale.Labels(13, 1), 'callback', "Fractale.Fonction = ''CosinusHyperbolique'';  actualiser(); rafraichir()")
	mFTh = uimenu(mF, 'label', Fractale.Labels(14, 1), 'callback', "Fractale.Fonction = ''TangenteHyperbolique''; actualiser(); rafraichir()")
	
	mF05 = uimenu(mF, 'label', ' ')
	
	mFEx = uimenu(mF, 'label', Fractale.Labels(15, 1), 'callback', "Fractale.Fonction = ''Exponentielle'';        actualiser(); rafraichir()")
	mFLn = uimenu(mF, 'label', Fractale.Labels(16, 1), 'callback', "Fractale.Fonction = ''Logarithme'';           actualiser(); rafraichir()")
	mFZz = uimenu(mF, 'label', Fractale.Labels(17, 1), 'callback', "Fractale.Fonction = ''Autopuissance'';        actualiser(); rafraichir()")
	
//	Menu de sélection du nombre de points
	mD = uimenu(interface, 'label', 'Dimensions');
	mD1 = uimenu(mD, 'label', '200 x 200', 'callback', "Fractale.Dimension = 200; rafraichir()")
	mD2 = uimenu(mD, 'label', '400 x 400', 'callback', "Fractale.Dimension = 400; rafraichir()")
	mD3 = uimenu(mD, 'label', '600 x 600', 'callback', "Fractale.Dimension = 600; rafraichir()")
	mD4 = uimenu(mD, 'label', '800 x 800', 'callback', "Fractale.Dimension = 800; rafraichir()")

//	Menu de sélection du nombre d'itérations
	mI = uimenu(interface, 'label', 'Itérations');
	mI1 = uimenu(mI, 'label', ' 100', 'callback', "Fractale.Iterations =  100; rafraichir()")
	mI2 = uimenu(mI, 'label', ' 500', 'callback', "Fractale.Iterations =  500; rafraichir()")
	mI3 = uimenu(mI, 'label', '1000', 'callback', "Fractale.Iterations = 1000; rafraichir()")
	mI4 = uimenu(mI, 'label', '2000', 'callback', "Fractale.Iterations = 2000; rafraichir()")

//	Menu de sélection du format d'enregistrement de la figure
	mS = uimenu(interface, 'label', 'Sauvegarde');
	mS1 = uimenu(mS, 'label', 'Format PNG', 'callback', "enregistrer(''PNG'')")
	mS2 = uimenu(mS, 'label', 'Format GIF', 'callback', "enregistrer(''GIF'')")
	mS3 = uimenu(mS, 'label', 'Format JPG', 'callback', "enregistrer(''JPG'')")
	mS4 = uimenu(mS, 'label', 'Format PDF', 'callback', "enregistrer(''PDF'')")

//	Initialisation du tracé
	axes_mandelbrot = newaxes();
	
	axes_mandelbrot.axes_bounds = [0, 0, 0.75, 0.75];
	axes_mandelbrot.margins = [0, 0, 0, 0];
	
	axes_mandelbrot.axes_visible = "off";
	axes_mandelbrot.x_location = "top";
	axes_mandelbrot.y_location = "left";
	axes_mandelbrot.box = "off";
	axes_mandelbrot.isoview = "on";
	axes_mandelbrot.data_bounds = [1, 1; Fractale.Dimension, Fractale.Dimension];
	
	axes_mandelbrot.tag = "traceMatrice";
	
	Matplot(zeros(Fractale.Dimension, Fractale.Dimension), "021")
	
	
//	Bandeau d'information
	bandeau_information = uicontrol(interface, "style", "text");
	bandeau_information.Position = [50 100 385 50];
	bandeau_information.FontSize = 15;
	bandeau_information.FontWeight = "bold";
	bandeau_information.HorizontalAlignment = "left";
	bandeau_information.String = "Ensemble de Mandelbrot" + Fractale.Texte;
	bandeau_information.BackgroundColor = [0.7 0.7 0.7];
	
	bandeau_information.tag = "infoBandeFonction";
	
//	Bandeau d'information
	bandeau2_information = uicontrol(interface, "style", "text");
	bandeau2_information.Position = [50 50 385 50];
	bandeau2_information.FontSize = 15;
	bandeau2_information.FontWeight = "bold";
	bandeau2_information.HorizontalAlignment = "left";
	bandeau2_information.String = string(Fractale.Dimension) + "x" + string(Fractale.Dimension) + " points | " + string(Fractale.Iterations) + " itérations";
	bandeau2_information.BackgroundColor = [0.7 0.7 0.7];
	
	bandeau2_information.tag = "infoBandeTaille";
	
//	Commande du tracé de l'ensemble de Mandelbrot
	mandelbrot_bouton = uicontrol(interface, "style", "pushbutton");
	mandelbrot_bouton.Units = "normalized";
	mandelbrot_bouton.Position = [0.8 0.9 0.2 0.1];
	mandelbrot_bouton.FontSize = 15;
	mandelbrot_bouton.String = "Mandelbrot";
	mandelbrot_bouton.BackgroundColor = Fractale.CouleurFond;
	mandelbrot_bouton.Callback = "tracer_Mandelbrot";
	mandelbrot_bouton.Relief = "raised";

//	Agrandissement de l'ensemble de Mandelbrot
	agrandissement_bouton = uicontrol(interface, "style", "pushbutton");
	agrandissement_bouton.Units = "normalized";
	agrandissement_bouton.Position = [0.8 0.7 0.2 0.1];
	agrandissement_bouton.FontSize = 15;
	agrandissement_bouton.String = "Agrandir";
	agrandissement_bouton.BackgroundColor = Fractale.CouleurFond;
	agrandissement_bouton.Callback = "tracer_Mandelbrot";
	agrandissement_bouton.Relief = "raised";
	agrandissement_bouton.Enable = "off";
	
//	Commande du tracé de l'ensemble de Julia
	julia_bouton = uicontrol(interface, "style", "pushbutton");
	julia_bouton.Units = "normalized";
	julia_bouton.Position = [0.8 0.5 0.2 0.1];
	julia_bouton.FontSize = 15;
	julia_bouton.String = "Julia";
	julia_bouton.BackgroundColor = Fractale.CouleurFond;
	julia_bouton.Callback = "tracer_Julia";
	julia_bouton.Relief = "raised";
	//julia_bouton.Enable = "off";
	
//	Commande du tracé de la fontière de l'ensemble de Julia
	julia_frontiere_bouton = uicontrol(interface, "style", "pushbutton");
	julia_frontiere_bouton.Units = "normalized";
	julia_frontiere_bouton.Position = [0.8 0.3 0.2 0.1];
	julia_frontiere_bouton.FontSize = 15;
	julia_frontiere_bouton.String = "J-frontière";
	julia_frontiere_bouton.BackgroundColor = Fractale.CouleurFond;
	julia_frontiere_bouton.Callback = "tracer_Julia_frontiere";
	julia_frontiere_bouton.Relief = "raised";
	//julia_frontiere_bouton.Enable = "off";

//	Commande de sortie du programme
	sortie_bouton = uicontrol(interface, "style", "pushbutton");
	sortie_bouton.Units = "normalized";
	sortie_bouton.Position = [0.8 0.1 0.2 0.1];
	sortie_bouton.FontSize = 15;
	sortie_bouton.String = "Sortir";
	sortie_bouton.BackgroundColor = Fractale.CouleurFond;
	sortie_bouton.Callback = "xdel(winsid())";
	sortie_bouton.Relief = "raised";
