# -*- coding: iso-8859-1 -*-
from __future__ import division # 1/2 == .5 (par defaut, 1/2 == 0)

##--------------------------------------#######
#                  Surfaces                   #
##--------------------------------------#######
#    WxGeometrie
#    Dynamic geometry, graph plotter, and more for french mathematic teachers.
#    Copyright (C) 2005-2007  Nicolas Pourcelot
#
#    This program is free software; you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation; either version 2 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program; if not, write to the Free Software
#    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

# version unicode


from API import *
from GUI import *
import matplotlib.axes3d


class SurfacesMenuBar(MenuBar):
    def __init__(self, panel):
        MenuBar.__init__(self, panel)

        self.ajouter(u"Fichier", [u"exporter"], [u"presse-papier"], [u"quitter"])
        self.ajouter(u"Affichage", [u"onglet"])#, ["repere"], ["quadrillage"], ["orthonorme"], ["fenetre"], ["zoomer"], ["dezoomer"], ["orthonormaliser"], [u"zoom_auto"])
        self.ajouter(u"Outils", [u"debug"], [u"options"])
        self.ajouter(u"?")




class Surfaces(Panel_API_graphique):
    
    __titre__ = u"Surfaces" # Donner un titre a chaque module
    
    def __init__(self, parent):
        
    
        #self.couleurs = u"bgrmkcy"


        Panel_API_graphique.__init__(self, parent)

        self.entrees = wx.BoxSizer(wx.VERTICAL)
        
        
        box = wx.StaticBox(self, -1, u"Equation")
        ligne = wx.StaticBoxSizer(box, wx.HORIZONTAL)
        ligne.Add(wx.StaticText(self, -1, "Z = "), 0, wx.ALIGN_CENTRE|wx.ALL,5)
        self.equation = wx.TextCtrl(self, size = (160, -1), style=wx.TE_PROCESS_ENTER)
        self.equation.Bind(wx.EVT_CHAR, self.EvtChar)
        ligne.Add(self.equation, 0, wx.ALIGN_CENTRE|wx.ALL,5)
        self.entrees.Add(ligne, 0, wx.ALL, 5)

        box = wx.StaticBox(self, -1, u"Abscisse")
        liste = wx.StaticBoxSizer(box, wx.VERTICAL)

        ligne = wx.BoxSizer(wx.HORIZONTAL)
        ligne.Add(wx.StaticText(self, -1, "Xmin"), 0, wx.ALIGN_CENTRE|wx.ALL,5)
        self.xmin = wx.TextCtrl(self, value = "-5", size = (160, -1), style=wx.TE_PROCESS_ENTER)
        self.xmin.Bind(wx.EVT_CHAR, self.EvtChar)
        ligne.Add(self.xmin, 0, wx.ALIGN_CENTRE|wx.ALL,5)
        liste.Add(ligne, 0, wx.ALL, 5)
        
        ligne = wx.BoxSizer(wx.HORIZONTAL)
        ligne.Add(wx.StaticText(self, -1, u"Xmax"), 0, wx.ALIGN_CENTRE|wx.ALL,5)
        self.xmax = wx.TextCtrl(self, value = "5", size = (160, -1), style=wx.TE_PROCESS_ENTER)
        self.xmax.Bind(wx.EVT_CHAR, self.EvtChar)
        ligne.Add(self.xmax, 0, wx.ALIGN_CENTRE|wx.ALL,5)
        liste.Add(ligne, 0, wx.ALL, 5)


        self.entrees.Add(liste, 0, wx.ALL, 5)

        box = wx.StaticBox(self, -1, u"Ordonnée")
        liste = wx.StaticBoxSizer(box, wx.VERTICAL)

        ligne = wx.BoxSizer(wx.HORIZONTAL)
        ligne.Add(wx.StaticText(self, -1, u"Ymin"), 0, wx.ALIGN_CENTRE|wx.ALL,5)
        self.ymin = wx.TextCtrl(self, value = "-5", size = (160, -1), style=wx.TE_PROCESS_ENTER)
        self.ymin.Bind(wx.EVT_CHAR, self.EvtChar)
        ligne.Add(self.ymin, 0, wx.ALIGN_CENTRE|wx.ALL,5)
        liste.Add(ligne, 0, wx.ALL, 5)
        
        ligne = wx.BoxSizer(wx.HORIZONTAL)
        ligne.Add(wx.StaticText(self, -1, u"Ymax"), 0, wx.ALIGN_CENTRE|wx.ALL,5)
        self.ymax = wx.TextCtrl(self, value = "5", size = (160, -1), style=wx.TE_PROCESS_ENTER)
        self.ymax.Bind(wx.EVT_CHAR, self.EvtChar)
        ligne.Add(self.ymax, 0, wx.ALIGN_CENTRE|wx.ALL,5)
        liste.Add(ligne, 0, wx.ALL, 5)

        self.entrees.Add(liste, 0, wx.ALL, 5)

        box = wx.StaticBox(self, -1, u"Pas")
        liste = wx.StaticBoxSizer(box, wx.VERTICAL)

        ligne = wx.BoxSizer(wx.HORIZONTAL)
        ligne.Add(wx.StaticText(self, -1, u"Pas"), 0, wx.ALIGN_CENTRE|wx.ALL,5)
        self.pas = wx.TextCtrl(self, size = (160, -1), style=wx.TE_PROCESS_ENTER)
        self.pas.Bind(wx.EVT_CHAR, self.EvtChar)
        ligne.Add(self.pas, 0, wx.ALIGN_CENTRE|wx.ALL,5)
        liste.Add(ligne, 0, wx.ALL, 5)
        liste.Add(wx.StaticText(self, -1, u"Exemple : 0.2 (évitez des valeurs trop faibles)."), 0, wx.ALL, 5)

        self.entrees.Add(liste, 0, wx.ALL, 5)

                
        #self.dessiner = wx.Button(self, wx.ID_REFRESH)
        #self.entrees.Add(self.dessiner, 0, wx.ALL, 5)
        self.sizer = wx.BoxSizer(wx.HORIZONTAL)
        self.sizer.Add(self.canvas, 1, wx.LEFT | wx.TOP | wx.GROW)
        self.sizer.Add(self.entrees, 0, wx.ALL, 5)
        self.SetSizer(self.sizer)
        self.Fit()
        self.initialisation_terminee = True

        #self.plot3d()
        
        
        
        
    def plot3d(self):
        # sample taken from http://www.scipy.org/Cookbook/Matplotlib/mplot3D
        ax3d = matplotlib.axes3d.Axes3D(self.canvas.figure)
        plt = self.canvas.figure.axes.append(ax3d)
        
        #delta = pi / 99.0
        #u = arange(0, 2*pi+(delta*2), delta*2)
        #v = arange(0, pi+delta, delta)
        
        #x=outerproduct(cos(u),sin(v))
        #y=outerproduct(sin(u),sin(v))
        #z=outerproduct(ones(size(u)), cos(v))
        #print x.shape, y.shape, z.shape
        
        #surf = ax3d.plot_wireframe(x,y,z)
        u = pylab.arange(-8, 4, .1)
        v = pylab.arange(-8, 4, .1)
        #x = outerproduct(u, ones(size(u)))
        #y = outerproduct(ones(size(v)), v)
        x = pylab.outer(u, pylab.ones(pylab.size(u)))
        y = pylab.outer(pylab.ones(pylab.size(v)), v)
        z = pylab.array([[i**2+j**2 for i in u] for j in v])
        surf = ax3d.plot_surface(x, y, z)
        surf.set_array(matplotlib.mlab.linspace(0, 1.0, 2*len(v)))
        #print surf.__class__
        ax3d.set_xlabel('X')
        ax3d.set_ylabel('Y')
        ax3d.set_zlabel('Z')

    
    def _sauvegarder(self, fgeo):
        Panel_API_graphique._sauvegarder(self, fgeo)
        fgeo.contenu[u"Courbe"] = [{"Y" : [self.equations[i].GetValue()], u"intervalle" : [self.intervalles[i].GetValue()], u"active" : [str(self.boites[i].GetValue())]} for i in range(self.nombre_courbes)]
        
    
    def _ouvrir(self, fgeo):
        Panel_API_graphique._ouvrir(self, fgeo)
        if fgeo.contenu.has_key(u"Courbe"):
            for i in range(min(len(fgeo.contenu[u"Courbe"]), self.nombre_courbes)):
                self.equations[i].SetValue(fgeo.contenu[u"Courbe"][i][u"Y"][0])
                self.intervalles[i].SetValue(fgeo.contenu[u"Courbe"][i][u"intervalle"][0])
                self.boites[i].SetValue(fgeo.contenu[u"Courbe"][i][u"active"][0] == u"True")
        self.affiche()


    
    def EvtChar(self, event):
        code = event.GetKeyCode()

        if code == 13:
            self.affiche()
        else:
            event.Skip()
            
        

        

    def _affiche(self):
        message = False
        self.ax3d = matplotlib.axes3d.Axes3D(self.canvas.figure)
        self.plt = self.canvas.figure.axes.append(self.ax3d)
        if not hasattr(self, "initialisation_terminee"):
            return
        xmin = securite.eval_safe(self.xmin.GetValue().strip())
        xmax = securite.eval_safe(self.xmax.GetValue().strip())
        ymin = securite.eval_safe(self.ymin.GetValue().strip())
        ymax = securite.eval_safe(self.ymax.GetValue().strip())

        pas = self.pas.GetValue().strip()
        if not pas:
            pas = self._param_.pas*max(xmax - xmin, ymax - ymin)
        else:
            pas = securite.eval_safe(pas)
        if pas < self._param_.pas_minimal*max(xmax - xmin, ymax - ymin):
            pas = self._param_.pas_minimal*max(xmax - xmin, ymax - ymin)
            self.canvas.message(u"Attention, le pas est trop petit !")
            message = True
        u = pylab.arange(xmin, xmax, pas)
        v = pylab.arange(ymin, ymax, pas)


        #x = outerproduct(u, ones(size(u)))
        #y = outerproduct(ones(size(v)), v)
        x = pylab.outer(u, pylab.ones(pylab.size(u)))
        y = pylab.outer(pylab.ones(pylab.size(v)), v)
        formule = Expression(self.equation.GetValue(), "xXyY", False, False, False).reformuler().replace(" ","")
        dico = globals().copy()  # evaluation securisee (certains modules et fonctions ne sont plus accessibles)
        dico.update(locals())
        try:
            z = pylab.array(securite.eval_restricted("[[ " + formule + " for x in u] for y in v]", dico))
            surf = getattr(self.ax3d, self._param_.mode)(x, y, z)
            surf.set_array(matplotlib.mlab.linspace(0, 1.0, 2*len(v)))
        except:
            if formule:
                print_error()
        #z = array([[i**2+j**2 for i in u] for j in v])
        #self.canvas.figure.clear()
        self.ax3d.set_xlabel('X')
        self.ax3d.set_ylabel('Y')
        self.ax3d.set_zlabel('Z')
        #self.ax3d.plot3d((0,10),(0,10),(0,10))
        if not message:
            self.canvas.message(u"Affichage actualisé.")

    

    
    
    









            

