# -*- coding: utf-8 -*-

"""
#####################################################
#                                                   #
#           EXERCICE RECAPITULATIF                  #
#                                                   #
#   Version de Anne-Julie Tinet                     #
#   complément Christine Fay-Varnier
#   L'ensemble de Mandelbrot                        #
#   mars 2020                                                #
#####################################################
"""

from complexe import Complexe
from suiteComplexe import SuiteComplexe

import numpy as np
import matplotlib.pyplot as pt

class EnsembleJulia:
    """La classe ensemble de Julia représente un ensemble de points du plan complexe 
    divergeant pour une suite donnée."""

    def __init__(self, xmin, xmax, ymin, ymax, nx, ny, p, c=None, niter=128, z=None):
        """

        @param xmin:
        @param xmax:
        @param ymin:
        @param ymax:
        @param nx:
        @param ny:
        @param p:
        @param c:
        @param u0:
        @param niter:
         L'ensemble est caractérisé :
         - par sa fenêtre dans le plan complexe (xmin-xmax),(ymin-ymax),
         - par le nombre de points dans chaque dimension de cet espace (nx,ny),
         - ainsi que par un ensemble de points divergeants pour une suite donnée (image_).
        """

        self.suite_ = SuiteComplexe(p, c, niter, z)
        self.xmin_ = xmin
        self.xmax_ = xmax
        self.ymin_ = ymin
        self.ymax_ = ymax

        self.nx_ = nx
        self.ny_ = ny

        # creation de l'image qui permet de représenter l'ensemble de Julia
        self.image_ = self.creeImage()

    def creeImage(self):
        """

        @return: l'ensemble de points de l'ensemble de Julia. La valeur de ces points est le nombre d'itérations
        à partir de laquelle la suite diverge divisé par le nombre d'itérations maximal possible.
        Si la suite ne diverge pas pour le nombre d'itérations maximal, la valeur est 1
        """

        # initialisation de la matrice selon les dimensions fixées
        image = np.zeros((self.ny_, self.nx_))

        # dx et dy pas entre deux valeurs sur les axes des x et des y
        dx = (self.xmax_ - self.xmin_) / self.nx_
        dy = (self.ymax_ - self.ymin_) / self.ny_

        # 1ère valeur des y (correspondent aux lignes)
        imag = self.ymin_
        for iy in range(self.ny_):
            # 1ère valeur des x pour une ligne (correspondent aux x)
            reel = self.xmin_
            for ix in range(self.nx_):
                # Création du complexe correspondant à la position dans 
                # la matrice. Attention, une matrice se dessine comme
                # on la lit. Par conséquent, les lignes correspondent à
                # y = cste et les colonnes à x = cste.

                # creation du complexe correspondant au point du plan d'indice iy, ix
                # de coordonnées reel, imag
                z = Complexe(reel, imag)

                # calcul de la valeur du point dans le plan
                image[iy, ix] = self.calculePoint(z)

                # passage à la colonne suivante
                reel = reel + dx

            # passage à la ligne suivante
            imag = imag + dy
        return image

    def calculePoint(self, z):
        """

        @param z:   valeur complexe correspondant à un point du plan
        @return:    Associe à z le nombre d'itérations pour que la suite diverge
                    divisé par le nombre d'itérations maximal possible
        """
        # Initialisation de la suite avec le point étudié
        # permet de savoir si le point est dans l'ensemble de Julia ou non
        self.suite_.set_u0(z)
        return self.suite_.diverge() / self.suite_.get_nbiter()

    def dessineImage(self):
        """

        @return: Reproduit l'image à l'écran en utilisant la méthode imshow de la
        bibliothèque matplotlib.pyplot
        """

        pt.imshow(self.image_, interpolation='none', extent=[self.xmin_, self.xmax_, self.ymin_, self.ymax_], origin="lower")
        pt.show()

if __name__ == '__main__':
    # essai sur le jeu de données de l'énoncé
    # c = Complexe(0.285, 0.01)
    # c = Complexe(-0.70176, -0.3842)

    # julia = EnsembleJulia(-1.0, 1.0, -1.0, 1.0, 200, 200, 2, c, niter=256)
    # julia.dessineImage()

    # c = Complexe(0.484, 0)
    # julia = EnsembleJulia(-1.0, 1.0, -1.0, 1.0, 200, 200, 4, c, niter=256)
    # julia.dessineImage()

    c = Complexe(-0.39, - 0.59)
    julia = EnsembleJulia(-1.0, 1.0, -1.0, 1.0, 200, 200, 2, c, niter=256)
    julia.dessineImage()