// Module PI : Peida Interactive     PIElDrawer
//	      E. Aubourg , R.Ansari     96-02
// (C) LAL (Orsay) / IN2P3-CNRS  DAPNIA/SPP (Saclay) / CEA

#include "sopnamsp.h"
#include "machdefs.h"
#include <strings.h>
#include <iostream>

#include "pieldrw.h"

#include <math.h>

/*  --------------------------------------------------------------  */
/*  ------------------- Classe PIElDrwMgr ------------------------  */
/*  --------------------------------------------------------------  */

//++
// Class	PIElDrwMgr
// Lib		PI
// include	pieldrw.h
//
//	Classe gestionnaire de tracé d'éléments. Utilisé par "PIElDrawer".
//--
//++
// Links	Voir aussi
// PIElDrawer
//--
//++
// Titre	Constructeurs et méthodes
//--

/* --Methode-- */
//++
PIElDrwMgr::PIElDrwMgr()
//	Constructeur
//--
{
  mEn = 0;
}

/* --Methode-- */
//++
PIElDrwMgr::~PIElDrwMgr()
//	destructeur
//--
{
  ElDelAll();
}

/* Des macros pour passer des coord normalise aux coord graphique */
#define CN_To_CG_X(x)  x0_g+dx_g*(double)x
#define CN_To_CG_Y(y)  y0_g+dy_g*(double)y
#define D_CN_To_CG_X(x)  dx_g*(double)x
#define D_CN_To_CG_Y(y)  dy_g*(double)y
#define CN_To_CG_R(r)  0.5*(dx_g+dy_g)*(double)r

/* --Methode-- */
//++
void PIElDrwMgr::DrawElements(PIGraphicUC* g, double xmin, double ymin, double xmax, double ymax)
//	Tracé des éléments
//--
{
  DrwElList::iterator it;
  g->SaveGraphicAtt();

  PIGrCoord x1g,x2g,y1g,y2g,xg,yg;
  double x0_g, dx_g, y0_g, dy_g;
  g->GetGrSpace(x1g,x2g,y1g,y2g);
  x0_g = x1g;  y0_g = y1g;
  dx_g = (double)x2g-(double)x1g;
  dy_g = (double)y2g-(double)y1g;

  for (it = mElist.begin(); it != mElist.end(); it++)
    {
      PIColors fcol = (*it).gatt.GetFgColor(); 
      if (fcol != PI_NotDefColor)    g->SelForeground(fcol);
      PIColors bcol = (*it).gatt.GetBgColor(); 
      if (bcol != PI_NotDefColor)    g->SelBackground(bcol);
      if ((*it).gatt.GetLineAtt() != PI_NotDefLineAtt)  
	g->SelLine((*it).gatt.GetLineAtt());
      if ( ((*it).gatt.GetFontName() != PI_DefaultFont) ||
	   ((*it).gatt.GetFontAtt() != PI_NotDefFontAtt) )
	g->SelFont((*it).gatt.GetFont());
      if ((*it).gatt.GetMarker() != PI_NotDefMarker) 
	g->SelMarker((*it).gatt.GetMarkerSize(), (*it).gatt.GetMarker());
      if ((*it).gatt.GetArrowMarker() !=  PI_NotDefArrowMarker) 
	g->SelArrowMarker((*it).gatt.GetArrowMarkerSize(), 
			  (*it).gatt.GetArrowMarker());

      switch ( (*it).etyp )
	{
	case PIDEL_Line :
	  if ((*it).scc)  // Coord specifie normalise 0..1
	    g->DrawLine(CN_To_CG_X((*it).ex), CN_To_CG_Y((*it).ey), 
			D_CN_To_CG_X((*it).edx), D_CN_To_CG_Y((*it).edy) ); 
	  else g->DrawLine((*it).ex, (*it).ey, (*it).edx, (*it).edy ); 
	  break;
	case PIDEL_Mark :
	  if ((*it).scc)  // Coord specifie normalise 0..1
	    g->DrawMarker(CN_To_CG_X((*it).ex), CN_To_CG_Y((*it).ey));
	  else g->DrawMarker((*it).ex, (*it).ey);
	  break;
	case PIDEL_Arrow :
	  if ((*it).scc)  // Coord specifie normalise 0..1
	    g->DrawArrowMarker(CN_To_CG_X((*it).ex), CN_To_CG_Y((*it).ey), 
			       D_CN_To_CG_X((*it).edx), D_CN_To_CG_Y((*it).edy) );
	  else g->DrawArrowMarker((*it).ex, (*it).ey, (*it).edx, (*it).edy, true); 
	  break;
	case PIDEL_Text :
	  if ((*it).scc)  // Coord specifie normalise 0..1
	    g->DrawString(CN_To_CG_X((*it).ex), CN_To_CG_Y((*it).ey),
			  ((*it).es->txt.c_str()), (*it).es->txtpd ); 
	  else g->DrawString((*it).ex, (*it).ey, ((*it).es->txt.c_str()), (*it).es->txtpd ); 
	  break;
	case PIDEL_CText :
	  if ((*it).scc) { // Coord specifie normalise 0..1
	    xg = CN_To_CG_X((*it).ex);
	    yg = CN_To_CG_Y((*it).ey);
	  }
	  else {
	    xg = (*it).ex;
	    yg = (*it).ey;
	  }
	  if ((*it).es->attss) 
	    g->DrawCompString(xg, yg, (*it).es->txt.c_str(), (*it).es->txt_up->c_str(),
			      (*it).es->txt_dn->c_str(), (*it).es->attss->GetFont(), 
			      (*it).es->txtpd );
	  else 
	    g->DrawCompString(xg, yg, (*it).es->txt.c_str(), (*it).es->txt_up->c_str(),
			      (*it).es->txt_dn->c_str(), (*it).es->txtpd );

	  break;
	case PIDEL_Rect :
	  if ((*it).scc)  // Coord specifie normalise 0..1
	    g->DrawBox(CN_To_CG_X((*it).ex), CN_To_CG_Y((*it).ey), 
		       D_CN_To_CG_X((*it).edx), D_CN_To_CG_Y((*it).edy) ); 
	  else 	g->DrawBox((*it).ex, (*it).ey, (*it).edx, (*it).edy ); 
	  break;
	case PIDEL_FRect :
	  if ((*it).scc)  // Coord specifie normalise 0..1
	    g->DrawFBox(CN_To_CG_X((*it).ex), CN_To_CG_Y((*it).ey), 
			D_CN_To_CG_X((*it).edx), D_CN_To_CG_Y((*it).edy) ); 
	  else g->DrawFBox((*it).ex, (*it).ey, (*it).edx, (*it).edy ); 
	  break;
	case PIDEL_Oval :
	  if ((*it).scc)  // Coord specifie normalise 0..1
	    g->DrawOval(CN_To_CG_X((*it).ex), CN_To_CG_Y((*it).ey), 
		       D_CN_To_CG_X((*it).edx), D_CN_To_CG_Y((*it).edy) ); 
	  else 	g->DrawOval((*it).ex, (*it).ey, (*it).edx, (*it).edy ); 
	  break;
	case PIDEL_FOval :
	  if ((*it).scc)  // Coord specifie normalise 0..1
	    g->DrawFOval(CN_To_CG_X((*it).ex), CN_To_CG_Y((*it).ey), 
			D_CN_To_CG_X((*it).edx), D_CN_To_CG_Y((*it).edy) ); 
	  else g->DrawFOval((*it).ex, (*it).ey, (*it).edx, (*it).edy ); 
	  break;
	case PIDEL_Circ :
	  if ((*it).scc)  // Coord specifie normalise 0..1
	    g->DrawCircle(CN_To_CG_X((*it).ex), CN_To_CG_Y((*it).ey), CN_To_CG_R((*it).er) );
	  else  g->DrawCircle((*it).ex, (*it).ey, (*it).er ); 
	  break;
	case PIDEL_FCirc :
	  if ((*it).scc)  // Coord specifie normalise 0..1
	    g->DrawFCircle(CN_To_CG_X((*it).ex), CN_To_CG_Y((*it).ey), CN_To_CG_R((*it).er) );
	  else g->DrawFCircle((*it).ex, (*it).ey, (*it).er ); 
	  break;
	case PIDEL_Arc :
	  if ((*it).scc)  // Coord specifie normalise 0..1
	    g->DrawArc(CN_To_CG_X((*it).ex), CN_To_CG_Y((*it).ey), CN_To_CG_R((*it).er),
		       CN_To_CG_R((*it).er), (*it).edx, (*it).edy );
	  else  g->DrawArc((*it).ex, (*it).ey, (*it).er, (*it).er, 
			   (*it).edx, (*it).edy ); 
	  break;
	case PIDEL_FArc :
	  if ((*it).scc)  // Coord specifie normalise 0..1
	    g->DrawFArc(CN_To_CG_X((*it).ex), CN_To_CG_Y((*it).ey), CN_To_CG_R((*it).er),
			CN_To_CG_R((*it).er), (*it).edx, (*it).edy );
	  else  g->DrawFArc((*it).ex, (*it).ey, (*it).er, (*it).er, 
			    (*it).edx, (*it).edy ); 
	  break;
	case PIDEL_Arc3P :
	  if ((*it).scc)  // Coord specifie normalise 0..1
	    g->Draw3PtArc(CN_To_CG_X((*it).xpol[0]), CN_To_CG_X((*it).xpol[1]), 
			  CN_To_CG_X((*it).xpol[2]), CN_To_CG_Y((*it).ypol[0]),
			  CN_To_CG_Y((*it).ypol[1]), CN_To_CG_Y((*it).ypol[1]) );
	  else g->Draw3PtArc((*it).xpol[0], (*it).ypol[0], (*it).xpol[1], 
			     (*it).ypol[1], (*it).xpol[2], (*it).ypol[2] );
	  break;
	case PIDEL_FArc3P :
	  if ((*it).scc)  // Coord specifie normalise 0..1
	    g->Draw3PtFArc(CN_To_CG_X((*it).xpol[0]), CN_To_CG_X((*it).xpol[1]), 
			   CN_To_CG_X((*it).xpol[2]), CN_To_CG_Y((*it).ypol[0]),
			   CN_To_CG_Y((*it).ypol[1]), CN_To_CG_Y((*it).ypol[1]) );
	  else  g->Draw3PtFArc((*it).xpol[0], (*it).ypol[0], (*it).xpol[1], 
			       (*it).ypol[1], (*it).xpol[2], (*it).ypol[2] );
	  break;
	case PIDEL_Poly :
	case PIDEL_FPoly :
	  if ((*it).scc) { // Coord specifie normalise 0..1
	    PIGrCoord* grx = new PIGrCoord[(*it).npol];
	    PIGrCoord* gry = new PIGrCoord[(*it).npol];
	    for(int jk=0; jk<(*it).npol; jk++) {
	      grx[jk] = CN_To_CG_X((*it).xpol[jk]);
	      gry[jk] = CN_To_CG_Y((*it).ypol[jk]);
	    }
	    if ((*it).etyp == PIDEL_Poly) 
	      g->DrawPolygon(grx, gry, (*it).npol, false ); 
	    else  g->DrawFPolygon(grx, gry, (*it).npol, false );
	    delete[] grx;
	    delete[] gry;
	  }
	  else {
	    if ((*it).etyp == PIDEL_Poly) 
	      g->DrawPolygon((*it).xpol, (*it).ypol, (*it).npol, false ); 
	    else g->DrawFPolygon((*it).xpol, (*it).ypol, (*it).npol, false ); 
	  }
	  break;
	default :
	  break;
	}
      g->RestoreGraphicAtt();
    }
}

//++
// int  ElAddText(double x, double y, const char* s, bool fgsc=false)
// int  ElAddText(double x, double y, const char* s, PIGraphicAtt gatt,  \
//                unsigned long tpd, bool fgsc=false)
// int  ElAddText(double x, double y, string const & s, bool fgsc=false)
// int  ElAddText(double x, double y, string const &  s, PIGraphicAtt gatt, \
//                unsigned long tpd, bool fgsc=false)
//	Ajout d'un élément texte (possibilité de spécification d'un attribut graphique
//	et d'un attribut de direction et de positionnement de texte "tpd").
//	si "fgsc==true", coordonnées spécifiées considerées normalisées entre 0 et 1.
//	Renvoie le numéro identificateur de l'élément.
// 
// int  ElAddCompText(double x, double y, string const& s, PIGraphicAtt const & gatt, \
//                    string const& s_up, string const& s_dn, \
//                    unsigned long tpd=0, bool fgsc=false)
// int  ElAddCompText(double x, double y, string const& s, PIGraphicAtt const & gatt, \
//                    string const& s_up, string const& s_dn, \
//                    unsigned long tpd=0, bool fgsc=false)
// int  ElAddCompText(double x, double y, string const& s, PIGraphicAtt const & gatt, \
//                    string const& s_up, string const& s_dn, PIGraphicAtt const & attss, \
//                    unsigned long tpd=0, bool fgsc=false)
//	Ajout d'un élément texte avec exposant ("s_up") et indice ("s_dn").
//	Il est possible de spécifier un attribut graphique ("gatt"), attribut de 
//	de direction et de positionnement de texte ("tpd"), ainsi qu'un attribut graphique
//	(fonte en particulier) pour le texte en exposant/indice ("attss").
//	si "fgsc==true", coordonnées spécifiées considerées normalisées entre 0 et 1.
//	Renvoie le numéro identificateur de l'élément.
//
// int  ElAddLine(double x1, double y1, double x2, double y2, bool fgsc=false)
// int  ElAddLine(double x1, double y1, double x2, double y2, PIGraphicAtt gatt, bool fgsc=false)
//	Ajout d'un élément de ligne (possibilité de spécification d'un attribut graphique).
//	si "fgsc==true", coordonnées spécifiées considerées normalisées entre 0 et 1.
//	Renvoie le numéro identificateur de l'élément.
//	
// int  ElAddRect(double x, double y, double dx, double dy, bool fgsc=false)
// int  ElAddRect(double x, double y, double dx, double dy, PIGraphicAtt gatt, bool fgsc=false)
//	Ajout d'un élément de type rectangle (possibilité de spécification d'un attribut graphique).
//	si "fgsc==true", coordonnées spécifiées considerées normalisées entre 0 et 1.
//	Renvoie le numéro identificateur de l'élément.
//
// int  ElAddFRect(double x, double y, double dx, double dy, bool fgsc=false)
// int  ElAddFRect(double x, double y, double dx, double dy,  PIGraphicAtt gatt, bool fgsc=false)
//	Ajout d'un élément de type rectangle plein 
//	(possibilité de spécification d'un attribut graphique).
//	si "fgsc==true", coordonnées spécifiées considerées normalisées entre 0 et 1.
//	Renvoie le numéro identificateur de l'élément.
//
// int  ElAddCirc(double x, double y, double r, bool fgsc=false)
// int  ElAddCirc(double x, double y, double r, PIGraphicAtt gatt, bool fgsc=false)
//	Ajout d'un élément de type cercle (possibilité de spécification d'un attribut graphique).
//	si "fgsc==true", coordonnées spécifiées considerées normalisées entre 0 et 1.
//	Renvoie le numéro identificateur de l'élément.
//
// int  ElAddFCirc(double x, double y, double r, bool fgsc=false)
// int  ElAddFCirc(double x, double y, double r, PIGraphicAtt gatt, bool fgsc=false)
//	Ajout d'un élément de type cercle plein avec un attribut de couleur.
//	si "fgsc==true", coordonnées spécifiées considerées normalisées entre 0 et 1.
//	Renvoie le numéro identificateur de l'élément.
//
// int  ElAddArc(double x, double y, double r, double a1, double da, bool fgsc=false)
// int  ElAddArc(double x, double y, double r, double a1, double da, \
//               PIGraphicAtt gatt, bool fgsc=false)
//	Ajout d'un élément de type arc de cercle défini par un angle de départ "a1"
//	et une extension angulaire "da". 
//	Il est possible de spécifier un attribut graphique.
//	si "fgsc==true", coordonnées spécifiées considerées normalisées entre 0 et 1.
//	Renvoie le numéro identificateur de l'élément.
//
// int  ElAddFArc(double x, double y, double r, double a1, double da, bool fgsc=false)
// int  ElAddFArc(double x, double y, double r, double a1, double da, \
//                PIGraphicAtt gatt, bool fgsc=false)
//	Ajout d'un élément de type arc de cercle plein défini par un angle de 
//	départ "a1" et une extension angulaire "da". 
//	Il est possible de spécifier un attribut graphique.
//	si "fgsc==true", coordonnées spécifiées considerées normalisées entre 0 et 1.
//	Renvoie le numéro identificateur de l'élément.
//
// int  ElAddArc(double x1, double y1, double x2, double y2 \
//               double x3, double y3, bool fgsc=false)
// int  ElAddArc(double x1, double y1, double x2, double y2 \
//               double x3, double y3, PIGraphicAtt gatt, bool fgsc=false)
//	Ajout d'un élément de type arc défini par trois points
//	(possibilité de spécification d'un attribut graphique).
//	si "fgsc==true", coordonnées spécifiées considerées normalisées entre 0 et 1.
//	Renvoie le numéro identificateur de l'élément.
//
// int  ElAddFArc(double x1, double y1, double x2, double y2 \
//                double x3, double y3, bool fgsc=false)
// int  ElAddFArc(double x1, double y1, double x2, double y2 \
//                double x3, double y3, PIGraphicAtt gatt, bool fgsc=false)
//	Ajout d'un élément de type arc plein défini par trois points
//	(possibilité de spécification d'un attribut graphique).
//	si "fgsc==true", coordonnées spécifiées considerées normalisées entre 0 et 1.
//	Renvoie le numéro identificateur de l'élément.
//
// int  ElAddPoly(vector<double>& x, vector<double>& y, bool fgsc=false)
// int  ElAddPoly(vector<double>& x, vector<double>& y, PIGraphicAtt gatt, bool fgsc=false)
//	Ajout d'un élément de type polygone (possibilité de spécification d'un attribut graphique).
//	si "fgsc==true", coordonnées spécifiées considerées normalisées entre 0 et 1.
//	Renvoie le numéro identificateur de l'élément.
//
// int  ElAddFPoly(vector<double>& x, vector<double>& y, bool fgsc=false)
// int  ElAddFPoly(vector<double>& x, vector<double>& y, PIGraphicAtt gatt, bool fgsc=false)
//	Ajout d'un élément de type polygone plein 
//	(possibilité de spécification d'un attribut graphique).
//	si "fgsc==true", coordonnées spécifiées considerées normalisées entre 0 et 1.
//	Renvoie le numéro identificateur de l'élément.
// 
// void  ElDel(int id)
//	Suppression de l'élément avec l'identificateur "id".
// void  ElDelLast()
//	Suppression du dernier élément ajouté.
// void  ElDelAll()
//	Suppression de tous les éléments de l'objet.
//--


/* --Methode-- */
int PIElDrwMgr::ElAdd(int typ, double x, double  y, double dx, double dy, 
		      const char* s, PIGraphicAtt const& att, 
		      unsigned long tpd, bool fgsc, double r)
{
  DrwEl dre;
  mEn++;
  dre.eid = mEn;  dre.etyp = typ;
  dre.ex = x;   dre.ey = y;
  dre.edx = dx;  dre.edy = dy;
  dre.er = r; 
  dre.gatt = att;
  if (s)  { 
    dre.es = new TxtEl;
    dre.es->txt = s;
    dre.es->txtpd = tpd;
    dre.es->txt_up = dre.es->txt_dn = NULL;
    dre.es->attss = NULL;
  }
  else dre.es = NULL;
  dre.xpol = dre.ypol = NULL;
  dre.npol = 0;
  dre.scc = fgsc;
  mElist.push_back(dre);
  return(mEn);
}

/* --Methode-- */
int PIElDrwMgr::ElAdd(double x, double y, const char* s, PIGraphicAtt const & att, const char* s_up, 
		      const char* s_dn, PIGraphicAtt const * gass, unsigned long tpd, bool fgsc)
{
  DrwEl dre;
  mEn++;
  dre.eid = mEn; dre.etyp = PIDEL_CText;
  dre.ex = x;   dre.ey = y;
  dre.edx = 0;  dre.edy = 0; 
  dre.er = 0.;
  dre.gatt = att;
  dre.es = new TxtEl;
  if (s) dre.es->txt = s;
  dre.es->txtpd = tpd;
  dre.es->txt_up = new string;
  if (s_up) *(dre.es->txt_up) = s_up;
  dre.es->txt_dn = new string;
  if (s_dn) *(dre.es->txt_dn) = s_dn;
  if (gass) dre.es->attss = new PIGraphicAtt(*gass);
  else dre.es->attss = NULL;
  dre.xpol = dre.ypol = NULL;
  dre.npol = 0;
  dre.scc = fgsc;
  mElist.push_back(dre);
  return(mEn);  
}

/* --Methode-- */
int PIElDrwMgr::ElAdd(int typ, vector<double>& x, vector<double>& y, 
		      PIGraphicAtt const& att, bool fgsc)
{
  DrwEl dre;
  mEn++;
  dre.eid = mEn;  dre.etyp = typ;
  dre.ex = dre.ey = 0;
  dre.edx = dre.edy = 0;
  dre.er = 0.;
  dre.gatt = att;
  dre.es = NULL;
  dre.xpol = dre.ypol = NULL;
  dre.npol = (y.size() < x.size()) ? y.size() : x.size();
  if (dre.npol > 0) {
    dre.xpol = new PIGrCoord[dre.npol];
    dre.ypol = new PIGrCoord[dre.npol];
    for(int kk=0; kk<dre.npol; kk++) {
      dre.xpol[kk] = x[kk];
      dre.ypol[kk] = y[kk];
    }
  }
  dre.scc = fgsc;
  mElist.push_back(dre);
  return(mEn);
}

/* --Methode-- */
int PIElDrwMgr::ElAdd(int typ, double* x, double* y, int n,
		      PIGraphicAtt const & att, bool fgsc)
{
  vector<double> vx, vy;
  for(int k=0; k<n; k++) {
    vx.push_back(x[k]);
    vy.push_back(y[k]);
  }
  return ( ElAdd(typ, vx, vy, att, fgsc) );
}


/* --Methode-- */
void  PIElDrwMgr::ElDel(int id)
{
  DrwElList::iterator it;
  for (it = mElist.begin(); it != mElist.end(); it++) {
    if ( (*it).eid == id) { 
      if ( (*it).es ) { 
        if ( (*it).es->txt_up ) delete (*it).es->txt_up;
        if ( (*it).es->txt_dn ) delete (*it).es->txt_dn;
        if ( (*it).es->attss ) delete (*it).es->attss;
        delete (*it).es;
      }
      if ( (*it).xpol ) delete[] (*it).xpol;
      if ( (*it).ypol ) delete[] (*it).ypol;
      mElist.erase(it);   
      break; 
    }
  }
  return;
}

/* --Methode-- */
void  PIElDrwMgr::ElDelAll()
{
  DrwElList::iterator it;
  for (it = mElist.begin(); it != mElist.end(); it++) {
    if ( (*it).es ) delete (*it).es;
    if ( (*it).xpol ) delete[] (*it).xpol;
    if ( (*it).ypol ) delete[] (*it).ypol;
  }
  mElist.erase(mElist.begin(), mElist.end());
  return;
}




/*  --------------------------------------------------------------  */
/*  ------------------- Classe PIElDrawer ------------------------  */
/*  --------------------------------------------------------------  */

//++
// Class	PIElDrawer
// Lib		PI
// include	pieldrw.h
//
//	Classe de traceur ("Drawer") capable de gérer et de 
//	tracer une liste d'éléments simples. Cette classe
//	est utilisé pour le tracé des axes et des éléments de
//	texte ds les "PIScDrawWdg", "PIDraw3DWdg" et "PIImage".
//--
//++
// Links	Parents
// PIDrawer
//--
//++
// Links	Voir aussi
// PIElDrwMgr
//--

//++
// Titre	Constructeurs et méthodes
//--

//++
// PIElDrawer(bool fgclip=true)
//	Constructeur - Si "fgclip=false", appel a PIGraphicUC::NoClip() ds Draw()
//--

/* --Methode-- */
PIElDrawer::PIElDrawer(bool fgclip)
{
fgClip = fgclip;
ShowTitles();
ShowAxesLabels();
}

/* --Methode-- */
PIElDrawer::~PIElDrawer()
{
}


//++
//  void  SetTitles(string tt, string tb)
//	Ajout de titres haut ("tt") et bas ("tb")
//--


/* --Methode-- */
int PIElDrawer::DecodeOptionString(vector<string> & opt, bool rmdecopt)
{
  int nopt0 = opt.size();
  if (nopt0 < 1)  return(0);  
  int ndec1 = PIDrawer::DecodeOptionString(opt, rmdecopt);
  if ((nopt0 - ndec1) < 1) return(ndec1);  // si tout a ete decode
  vector<string> udopt;
  unsigned int k = 0;
  int ndec = opt.size();
  for( k=0; k<opt.size(); k++ ) {
    string opts = opt[k];
    if ( (opts == "stdaxes") || (opts == "defaxes") || (opts == "boxaxes") )
      SetAxesFlags(kAxesDflt);
    else if (opts == "boxaxesgrid")
      SetAxesFlags(kAxesDflt | kGridOn);
    else if (opts == "fineaxes") 
      SetAxesFlags(kAxesDflt | kMinTicks | kMajTicks);
    else if (opts == "fineaxesgrid")
      SetAxesFlags(kAxesDflt | kMinTicks | kMajTicks | kGridOn);
    else if (opts == "centeredaxes")
      SetAxesFlags(kCentAxes | kTicks | kMajTicks | kLabels);
    else if (opts == "finecenteredaxes")
      SetAxesFlags(kCentAxes | kTicks | kMajTicks | kMinTicks | kLabels);
    else if (opts == "centeredaxesgrid")
      SetAxesFlags(kCentAxes | kTicks | kMajTicks | kLabels | kGridOn);
    else if (opts == "finecenteredaxesgrid")
      SetAxesFlags(kCentAxes | kTicks | kMajTicks | kMinTicks | kLabels | kGridOn);
    else if (opts == "axesnone")
      SetAxesFlags(kAxesNone);
    else if (opts == "labels")
      SetAxesFlags(GetAxesFlags() | kLabels);
    else if (opts == "nolabels")
      SetAxesFlags(GetAxesFlags() & ~kLabels);
    else if (opts == "hlabels")
      SetAxesFlags(GetAxesFlags() | kLabelsH);
    else if (opts == "nohlabels")
      SetAxesFlags(GetAxesFlags() & ~kLabelsH);
    else if (opts == "vlabels")
      SetAxesFlags(GetAxesFlags() | kLabelsV);
    else if (opts == "novlabels")
      SetAxesFlags(GetAxesFlags() & ~kLabelsV);
    else if (opts == "ticks")
      SetAxesFlags(GetAxesFlags() | kTicks);
    else if (opts == "noticks")
      SetAxesFlags(GetAxesFlags() & ~kTicks);
    else if (opts == "minorticks")
      SetAxesFlags(GetAxesFlags() | kMinTicks);
    else if (opts == "nominorticks")
      SetAxesFlags(GetAxesFlags() & ~kMinTicks);
    else if (opts == "extticks")
      SetAxesFlags((GetAxesFlags() & ~kIntTicks) |  kExtTicks);
    else if (opts == "intticks")
      SetAxesFlags((GetAxesFlags() & ~kExtTicks) |  kIntTicks);
    else if (opts == "extintticks")
      SetAxesFlags(GetAxesFlags() | kIntTicks |  kExtTicks);
    else if (opts == "grid")
      SetAxesFlags(GetAxesFlags() | kGridOn);
    else if (opts == "nogrid")
      SetAxesFlags(GetAxesFlags() & ~kGridOn);
    else if (opts.substr(0,11) == "axescenter=") {
      if(opts == "axescenter=") {
        axeDr.ConfigureAxesCenter();
      } else {
        double x0=0., y0=0.;
        sscanf(opts.substr(11).c_str(),"%lf,%lf",&x0,&y0);
        axeDr.ConfigureAxesCenter(true,x0,y0);
      }
    }
 
    else if (opts == "title" || opts == "tit") ShowTitles(true);
    else if (opts == "notitle" || opts == "notit") ShowTitles(false);
    else if (opts.substr(0,8) == "nbticks=") {
      int xnticks=0;
      int ynticks=0;
      sscanf(opts.substr(8).c_str(),"%d,%d", &xnticks, &ynticks);
      ConfigureAxeTicks(xnticks, ynticks, 0., 0.);
    }
    else if (opts.substr(0,9) == "tickslen=") {
      double fmajtl = 0.;
      double fmintl = 0.;
      sscanf(opts.substr(9).c_str(),"%lg,%lg", &fmajtl, &fmintl);
      ConfigureAxeTicks(0, 0, fmajtl, fmintl);
    }
    else {
      ndec--;
      if (rmdecopt)  udopt.push_back(opts);
    }
  }  

  if (rmdecopt)  opt = udopt;
  return(ndec+ndec1);
}
/* --Methode-- */
void PIElDrawer::GetOptionsHelpInfo(string& info)
{
  info += " ---- PIElDrawer options help info : \n" ;
  info += " >> Axe and grid configuration flags: \n";
  info += "   axesnone  stdaxes defaxes \n";
  info += "   boxaxes boxaxesgrid fineaxes fineaxesgrid \n";
  info += "   centeredaxes finecenteredaxes centeredaxesgrid \n";
  info += "   finecenteredaxesgrid  grid/nogrid \n";
  info += " >> Centered axes position: axescenter=xc,yc \n";
  info += " >> Axe ticks/labels (h=horizontal/x, v=vertical/y): \n"; 
  info += "   labels/nolabels  hlabels/nohlabels vlabels/novlabels \n";
  info += "   ticks/noticks minorticks/nominorticks \n";
  info += "   extticks/intticks/extintticks nbticks=X_NbTicks,Y_NbTicks \n";
  info += "   tickslen=MajorTickLenFrac,MinorTickLenFraC \n"; 
  info += " >> Axe labels font size: \n";
  info += "    autofontsize=FontSizeFrac fixedfontsize \n";
  info += " >> Up/Down title: title tit notitle notit \n";
  info += "    ... Color/Font/line attributes : \n";
// On recupere ensuite la chaine info de la classe de base
  PIDrawer::GetOptionsHelpInfo(info);
  return;  
}

/* --Methode-- */
void  PIElDrawer::DrawAxes(PIGraphicUC* g)
{
  if (axesFlags == kAxesNone) return;
  //  g->NoClip();
  axeDr.DrawXYAxes(g, mGrAtt, XMin(), XMax(), YMin(), YMax(), 
		   axesFlags, mAFSz, mFontSzF); 
  if (showAxesLabels) { 
    axeDr.DrawXCaption(g, labelAtt, axesFlags, xLabel);
    axeDr.DrawYCaption(g, labelAtt, axesFlags, yLabel);
  }
  //  g->Clip();
}

/* --Methode-- */
void  PIElDrawer::Draw(PIGraphicUC* g, double xmin, double ymin, double xmax, double ymax)
{
SelGraAtt(g);   
if (!fgClip) g->NoClip();
DrawAxes(g);   // Trace des axes 
// g->SelFont(PI_NormalSizeFont);

// Trace des titres 
if ( showTitles && ((titleT.length() > 0) || (titleB.length() > 0)) ) {
  PIGraphicAtt grs = GetGraphicAtt();
  UpdateGraphicAtt(titleAtt);
  SelGraAtt(g); 

  aXdir = false;  // Vrai si Axe X de Droite vers Gauche 
  aYdir = false;  // Vrai si Axe Y de Haut vers Bas
  double fx, fy, fh;
  fx = g->DeltaUCX(XMin(), 0.5*(XMax()-XMin()));
		   
//  fh = g->GetFontHeightUC(gas, gds);
  if ( titleT.length() > 0) {
    fh = 0.04*(YMax()-YMin());
    if (g->isAxeYDirUpDown()) fy = g->DeltaUCY(YMin(), -fh);
    else fy = g->DeltaUCY(YMax(), fh);
    g->DrawString(fx, fy, titleT.c_str(), PI_HorizontalCenter | PI_VerticalBottom);
    //      printf(" PIElDrawer::Draw()/DBG (%g , %g) %s  - %g \n", fx, fy, titleT.c_str(), fh);
  }
  if ( titleB.length() > 0) {
    fh = 0.075*(YMax()-YMin());
    if (g->isAxeYDirUpDown()) fy =  g->DeltaUCY(YMax(), fh);
    else fy = g->DeltaUCY(YMin(), -fh);
    g->DrawString(fx, fy, titleB.c_str(), PI_HorizontalCenter | PI_VerticalTop);
    //      printf(" PIElDrawer::Draw()/DBG (%g , %g) %s  - %g \n", fx, fy, titleT.c_str(), fh);
  }
  SetGraphicAtt(grs); 
}
 SelGraAtt(g);
 // Trace des elements
 ElDrwMgr().DrawElements(g, xmin, ymin, xmax, ymax);

}

/* --Methode-- */
double  PIElDrawer::GetDistanceToPoint(double x, double y) 
{
  double dist,disty,distx,d1,d2;
  bool fgokx, fgoky;
  d1 = fabs(x-XMin());
  d2 = fabs(x-XMax());
  if ((y<YMax()) && (y>YMin()))  { 
    distx = (d1 < d2) ? d1 : d2;
    distx /= 0.5*(XMax()-XMin());
    fgokx = true;
  }
  else fgokx = false;
  d1 = fabs(y-YMin());
  d2 = fabs(y-YMax());
  if ((x<XMax()) && (x>XMin()))  { 
    disty = (d1 < d2) ? d1 : d2;
    disty /= 0.5*(YMax()-YMin());
    fgoky = true;
  }
  else fgoky = false;
  if (!fgokx  && !fgoky)  return PIDrawer::GetDistanceToPoint(x,y);
  else {
    if (fgokx && fgoky) dist = (distx<disty) ? distx : disty;
    else if (fgokx) dist = distx;
    else dist = disty;
  }
  return dist;
}
