// Module PI : Peida Interactive     PIGraphicUC 
// Trace graphiques User-Coordinates    R. Ansari  97
// LAL (Orsay) / IN2P3-CNRS  DAPNIA/SPP (Saclay) / CEA

#include "machdefs.h"
#include <iostream>
#include "pigraphuc.h"

#include "ucckprot.h"


//++
// Class	PIGraphicUC
// Lib		PI
// include	pigraphuc.h
//
//   	Classe fournissant les services de tracé graphique 
//	en coordonnées utilisateur.
//	Toutes les méthodes de tracé de "PIGraphic" sont redéfinies pour 
//	accepter les arguments en système de coordonnées utilisateur.
//--
//++
// Links	Parent
// PIGraphic
//--

// Pour echanger deux valeurs PIGrCoord
static inline void dbl_swap(double& a, double& b) { double tmp = a; a = b; b = tmp; }

//++
// Titre	Constructeurs, méthodes
//--
//++
// PIGraphicUC(PIGraphicGen* g, PIGrCoord x0, PIGrCoord y0, PIGrCoord dx, PIGrCoord dy)
//	Constructeur d'un objet "PIGraphUC" à partir d'un "PIGraphicGen* g". L'espace
//	de travail du nouvel objet "PIGraphic" correspond au rectangle défini par
//	"(x0,y0)" , "dx,dy" du "PIGraphic" de départ.
// 
// int  kind()
//	Renvoie le type ("= PI_UCGraphics")
// void SetBaseGraphic(PIGraphicGen* g, PIGrCoord x0, PIGrCoord y0, PIGrCoord dx, PIGrCoord dy)
//	Permet de modifier l'objet "PIGraphic" de départ et l'espace graphique correspondant.
//
// void  SelFontSz(PIGrCoord sz)
//	Sélection de fonte avec la taille exprimée en coordonnées utilisateur
// void  SelFontSz(PIGrCoord sz, PIFontAtt att)
//	Sélection de fonte avec la taille exprimée en coordonnées utilisateur, avec 
//	Spécification d'attribut de fonte
// void  SelMarkerSz(PIGrCoord msz, PIMarker mrk=PI_DotMarker)
//	Sélection de marker avec la taille exprimée en coordonnées utilisateur
//--

/* --Methode-- */
PIGraphicUC::PIGraphicUC(PIGraphicGen* g, PIGrCoord x0, PIGrCoord y0, PIGrCoord dx, PIGrCoord dy)
  : PIGraphicGen()
{
  mGrC = g;
  xW0 = x0;  yW0 = y0; 
  xWd = dx;  yWd = dy; 
  aXdir = false;  // Vrai si Axe X de Droite vers Gauche 
  aYdir = false;  // Vrai si Axe Y de Haut vers Bas
  aXlog = aYlog = false;   // Vrai -> Echelle log
  aXYexchng = false;       // Vrai -> Echange axes X,Y UserX,Y --> WindowY, X
  SetUCS(0., 1., 0., 1., kAxeDirLtoR, kAxeDirDownUp);
  SetLogScale(false, false);
  clip = true;  
}

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

/* --Methode-- */
int PIGraphicUC::kind() 
{
return PI_UCGraphics; 
}


/* --Methode-- */
void PIGraphicUC::SetBaseGraphic(PIGraphicGen* g, PIGrCoord x0, PIGrCoord y0, PIGrCoord dx, PIGrCoord dy)
{
  mGrC = g;
  xW0 = x0;  yW0 = y0; 
  xWd = dx;  yWd = dy; 
  SetUCS(xMin, xMax, yMin, yMax, kAxeDirSame, kAxeDirSame);
}

/* --Methode-- */
void PIGraphicUC::GetGrSpace(PIGrCoord& xmin, PIGrCoord& xmax, PIGrCoord& ymin, PIGrCoord& ymax)
{
xmin = xMin;  ymin = yMin;  
xmax = xMax;  ymax = yMax;
}

//++
// Titre	Système de coordonnées utilisateur
//--
//++
// void       SetUCS(double xmin, double xmax, double ymin, double ymax, -
// int axrl=kAxeDirSame, int ayud=kAxeDirSame)
//	Définit le système de coordonnées utilisateur. Axe X de "xmin" à "xmax" , 
//	Axe Y de "ymin" à "ymax". "axrl", "ayud" définit le sens des axes 
//	sur la fenêtre :
//|	kAxeDirSame : Pas de changement de sens
//|	kAxeDirLtoR : Axe X croissant de gauche à droite   
//|	kAxeDirRtoL : Axe X croissant de droite à gauche 
//|	kAxeDirDownUp : Axe Y croissant de Bas vers Haut
//|	kAxeDirUpDown : Axe Y croissant de Haut vers Bas
//|	kAxeDirAuto : Sens determine a partir de la valeur relative 
//|	de xmin, xmax, ymin, ymax
//|	      xmin < xmax : kAxeDirLtoR   -  xmax < xmin : kAxeDirRtoL
//|	      ymin < ymax : kAxeDirDownUp -  ymax < ymin : kAxeDirUpDown
//	Par défaut : "xmin=ymin=0." , "ymin=ymax=0." , "kAxeDirLtoR" , "kAxeDirDownUp"
// 
// void  SetLogScale(bool logx, bool logy)
//	Définition d'échelle logarithmique pour l'axe X,Y (si X,Ymin max > 0).
//	Si X,Ymin max sont modifiés par SetUCS par la suite, avec des 
//	valeurs négatives, l'échelle est remise en linéaire.
// bool  isLogScaleX()  
// bool  isLogScaleY() 
//	Renvoie "true" si échelle logarithmique pour l'axe X,Y
// bool  isAxeXDirRtoL()
//	Renvoie "true" si axe X de droite a gauche
// bool  isAxeYDirUpDown()
//	Renvoie "true" si axe Y de haut vers vbas.
//	
// void  UC2GrC(double x, double y, double& xpix, double& ypix)
//	Transformation de coordonnées utilisateur "(x,y)" en coordoonnées 
//	de l'espace graphic de départ "(xpix, ypix)"
// void  GrC2UC(double xpix, double ypix, double& x, double& y)
//	Transformation de coordonnées de l'espace graphic de départ. en coordonnées utilisateur.
// void  DUC2GrC(double dx, double dy, double& dxpix, double& dypix)
//	Transformation de distances selon X,Y en coordonnées utilisateur "dx, dy" en distance
//	dans l'espace graphique de départ "dxpix , dypix".
// void  DGrC2UC(double dxpix, double dypix, double& dx, double& dy)
//	Transformation de distances selon X,Y dans l'espace graphique de départ en distance
//	dans l'espace de  coordonnées utilisateur.
//
// void  LinUC2GrC(double x, double y, double& xpix, double& ypix)
//	Transformation de coordonnées utilisateur "(x,y)" en coordoonnées 
//	de l'espace graphic de départ "(xpix, ypix)", sans utilisation de 
//	l'échelle logarithmique.
// double  DeltaUCX(double x, double dx)
//	Retourne la nouvelle coordonnée X, correspondant a "x" décalée de
//	"dx", avec "dx" exprimé en échelle linéaire.
// double  DeltaUCY(double y, double dy)
//	Retourne la nouvelle coordonnée Y, coorespondant a "y" décalée de
//	"dy", avec "dy" exprimé en échelle linéaire.
//--

/* --Methode-- */
void PIGraphicUC::SetUCS(double xmin, double xmax, double ymin, double ymax,
                         int axrl, int ayud, bool exchxy)
{
  if (axrl == kAxeDirAuto) {
    double ff;
    if (xmax < xmin)  { axrl = kAxeDirRtoL;   ff=xmin;  xmin=xmax;  xmax=ff; }
    else  axrl = kAxeDirLtoR;
  }
  if (ayud == kAxeDirAuto) {
    double ff;
    if (ymax < ymin)  { ayud = kAxeDirUpDown;   ff=ymin;  ymin=ymax;  ymax=ff; }
    else  ayud = kAxeDirDownUp;
  }

  UC_CheckMinMaxDiff(xmin, xmax);
  UC_CheckMinMaxDiff(ymin, ymax);

  if (!UC_CheckFinite(xmin, xmax) || !UC_CheckFinite(ymin, ymax)) {
    cerr << "PIGraphicUC::SetUCS() Error - Non finite value for x/ymin-max ! " << endl;
    return; 
    }

  if (axrl == kAxeDirLtoR)  aXdir = false;
  else if (axrl == kAxeDirRtoL)  aXdir = true;
  if (ayud == kAxeDirDownUp)  aYdir = false;
  else if (ayud == kAxeDirUpDown)  aYdir = true;
  xMin = xmin;
  xMax = xmax;
  yMin = ymin;
  yMax = ymax;

  xScale = UC_LimitProtectDouble(xWd/(xMax-xMin)); // Protection 
  if (aXdir)  { 
    xScale = -xScale;
    xOrg   = -xMax * xScale;
  }
  else xOrg   = -xMin * xScale;
  xOrg += xW0;

  yScale = UC_LimitProtectDouble(yWd/(yMax-yMin)); // Protection  
  if (!aYdir) {
    yScale = -yScale;
    yOrg   = -yMax  * yScale;
    }
  else yOrg   = -yMin * yScale;
  yOrg += yW0;
  if (aXlog || aYlog) SetLogScale(aXlog, aYlog);
  return;
}

/* --Methode-- */
void PIGraphicUC::SetLogScale(bool logx, bool logy)
{
if (logx) 
  if (xMax < PETIT_DBLE) {
    cerr<< "PIGraphicUC::SetLogScale() Warning - XLogScale not valid for XMax ="
        << xMax<<" < "<<PETIT_DBLE<<endl;
    logx = false;
  }
if (logy)
  if (yMax < PETIT_DBLE) {
    cerr<<"PIGraphicUC::SetLogScale() Warning - YLogScale not valid for YMax ="
        <<yMax<<" < "<<PETIT_DBLE<<endl;
    logy = false;
  }

aXlog = logx;
aYlog = logy;

if (aXlog) {     
  xMinLog = (xMin > PETIT_DBLE) ? xMin : ( (1. < xMax/10.) ? 1. : xMax/10.);
  xScaleLog = xWd*(xMax-xMinLog)/(xMax-xMin) / (log10(xMax)-log10(xMinLog));
  xScaleLog = UC_LimitProtectDouble(xScaleLog); // Protection 
  if (aXdir)  { 
    xScaleLog = -xScaleLog;
    xOrgLog   = -log10(xMax) * xScaleLog + (xOrg + xMax*xScale);
  }
  else xOrgLog   = -log10(xMinLog) * xScaleLog + (xOrg + xMinLog*xScale);
  //  if (xMinLog > xMin) 
  //    cerr << "PIGraphicUC::SetLogScale() Warning - Linear Scale for X < " << xMinLog << endl;
}
else {
  xMinLog = 1.;
  xScaleLog = xScale;
  xOrgLog = xW0;
}
if (aYlog) {     
  yMinLog = (yMin > PETIT_DBLE) ? yMin : ( (1. < yMax/10.) ? 1. : yMax/10.);
  yScaleLog = yWd*(yMax-yMinLog)/(yMax-yMin) / (log10(yMax)-log10(yMinLog));
  yScaleLog = UC_LimitProtectDouble(yScaleLog); // Protection 
  if (!aYdir) {
    yScaleLog = -yScaleLog;
    yOrgLog   = -log10(yMax)  * yScaleLog + (yOrg + yMax*yScale);
    }
  else yOrgLog   = -log10(yMinLog) * yScaleLog + (yOrg + yMinLog*yScale);
  //  if (yMinLog > yMin) 
  //    cerr << "PIGraphicUC::SetLogScale() Warning - Linear Scale for Y < " << yMinLog << endl;
}  
else {
  yMinLog = 1.;
  yScaleLog = xScale;
  yOrgLog = xW0;
}
return;
}

/* --Methode-- */
void PIGraphicUC::UC2GrC(double x, double y, double& xpix, double& ypix)
{
  if (aXlog && (x > xMinLog))  xpix = xOrgLog + log10(x)*xScaleLog;  
  else xpix = (double)(xOrg + x*xScale);  
  if (aYlog && (y > yMinLog))  ypix = yOrgLog + log10(y)*yScaleLog; 
  else ypix = (double)(yOrg + y*yScale);  
}

/* --Methode-- */
void PIGraphicUC::GrC2UC(double xpix, double ypix, double& x, double& y)
{
  if (!aXlog)  x = (xpix-xOrg)/xScale;
  else { 
    if ( (aXdir && (xpix < (xOrg + xMinLog*xScale))) || 
         (!aXdir && (xpix > (xOrg + xMinLog*xScale))) )     {
      x = (xpix-xOrgLog)/xScaleLog;
      x = pow(10., x);
    }
    else x = (xpix-xOrg)/xScale;
  }
       
  if (!aYlog)  y = (ypix-yOrg)/yScale;
  else { 
    if ( (aYdir && (ypix > (yOrg + yMinLog*yScale))) || 
         (!aYdir && (ypix < (yOrg + yMinLog*yScale))) )    {
      y = (ypix-yOrgLog)/yScaleLog;
      y = pow(10., y);
    }
    else y = (ypix-yOrg)/yScale;
  }

}

/* --Methode-- */
void PIGraphicUC::DUC2GrC(double dx, double dy, double& dxpix, double& dypix)
{
  dxpix = dx*xScale;
  if (dxpix < 0)  dxpix = -dxpix;
  dypix = dy*yScale;
  if (dypix < 0)  dypix = -dypix;
}

/* --Methode-- */
void PIGraphicUC::DGrC2UC(double dxpix, double dypix, double& dx, double& dy)
{
  dx = dxpix/xScale;
  dy = dypix/yScale;
  if (dx < 0.) dx = -dx;
  if (dy < 0.) dy = -dy;
}

/* --Methode-- */
void PIGraphicUC::LinUC2GrC(double x, double y, double& xpix, double& ypix)
{
  xpix = (double)(xOrg + x*xScale);  
  ypix = (double)(yOrg + y*yScale);  
}

/* --Methode-- */
double PIGraphicUC::DeltaUCX(double x, double dx)
{
  if (!aXlog) return(x+dx);
  double xpix, dxpix, tmp, ret;
  UC2GrC(x, yMin, xpix, tmp); 
  DUC2GrC(dx, 0., dxpix, tmp);
  if ( ((dx < 0.) && !aXdir) || ((dx >= 0.) && aXdir) )  dxpix = -dxpix;
  GrC2UC(xpix+dxpix, yW0, ret, tmp);
  return(ret);  
}

/* --Methode-- */
double PIGraphicUC::DeltaUCY(double y, double dy)
{
  if (!aYlog) return(y+dy);
  double ypix, dypix, tmp, ret;
  UC2GrC(xMin, y, tmp, ypix); 
  DUC2GrC(0, dy, tmp, dypix);
  if ( ((dy < 0.) && aYdir) || ((dy >= 0.) && !aYdir) )  dypix = -dypix;
  GrC2UC(xW0, ypix+dypix, tmp, ret);
  return(ret);  
}



/* --Methode-- */
void PIGraphicUC::Erase(PIGrCoord xc, PIGrCoord yc, PIGrCoord dxc, PIGrCoord dyc)
{
  if (!mGrC) return;
  double x, y, dx, dy;
  x = xc;  dx = dxc;
  y = yc;  dy = dyc;
  if (clip) {
    if (dx < 0) {
      x = x+dx;
      dx = -dx;
    }
    if (dy < 0) {
      y = y+dy;
      dy = -dy;
    }
    if (x > xMax || x+dx < xMin || y > yMax || y+dy < yMin) return;
    if (x < xMin) {
      dx -= (xMin-x);
      x = xMin;
    }
    if (y < yMin) {
      dy -= (yMin-y);
      y = yMin;
    }
    if (x+dx > xMax)
      dx = (xMax-x);
    if (y+dy > yMax)
      dy = (yMax-y);
  }

  double xf, yf, xf2, yf2;
  UC2GrC(x, y, xf, yf);
  UC2GrC(x+dx, y+dy, xf2, yf2);
  if (xf2 < xf)  dbl_swap(xf, xf2);
  if (yf2 < yf)  dbl_swap(yf, yf2);
  mGrC->Erase(xf, yf, xf2-xf, yf2-yf);
}

/* --Methode-- */
void PIGraphicUC::DrawString(PIGrCoord x, PIGrCoord y, const char* s, unsigned long pos)
{
  if (!mGrC) return;
  double xf, yf;
  UC2GrC(x, y, xf, yf);
  mGrC->DrawString(xf, yf, s, pos);  
}

/* --Methode-- */
void PIGraphicUC::DrawOpaqueString(PIGrCoord x, PIGrCoord y, const char* s, unsigned long pos)
{
  if (!mGrC) return;
  double xf, yf;
  UC2GrC(x, y, xf, yf);
  mGrC->DrawOpaqueString(xf, yf, s, pos);  
}

/* --Methode-- */
void PIGraphicUC::DrawCompString(PIGrCoord x, PIGrCoord y, const char* s, 
				 const char* s_up, const char* s_dn, 
				 PIFont const & fntss, unsigned long pos)
{
  if (!mGrC) return;
  double xf, yf;
  UC2GrC(x, y, xf, yf);
  mGrC->DrawCompString(xf, yf, s, s_up, s_dn, fntss, pos);
}

/* --Methode-- */
void PIGraphicUC::DrawLine(PIGrCoord xc1, PIGrCoord yc1, PIGrCoord xc2, PIGrCoord yc2)
{
  
  if (!mGrC) return;
  double x1, y1, x2, y2;
  x1 = xc1;  y1 = yc1;
  x2 = xc2;  y2 = yc2;
  if (clip) {
    if (x2 < xMin && x1 < xMin) return;
    if (x2 > xMax && x1 > xMax) return;
    if (y1 < yMin && y2 < yMin) return;
    if (y1 > yMax && y2 > yMax) return;
    if (x2 < x1) {
      dbl_swap(x1,x2);
      dbl_swap(y1,y2);
    }
    if (x2>xMax) {
      y2 = y1 + (y2-y1)/(x2-x1)*(xMax-x1);
      x2 = xMax;
    }
    if (x1<xMin) {
      y1 = y2 + (y1-y2)/(x1-x2)*(xMin-x2);
      x1 = xMin;
    }
    if (y2 < y1) {
      dbl_swap(x1,x2);
      dbl_swap(y1,y2);
    }
    if (y2>yMax) {
      x2 = x1 + (x2-x1)/(y2-y1)*(yMax-y1);
      y2 = yMax;
    }
    if (y1<yMin) {
      x1 = x2 + (x1-x2)/(y1-y2)*(yMin-y2);
      y1 = yMin;
    }
  }

  double xf1, yf1, xf2, yf2;
  UC2GrC(x1, y1, xf1, yf1);
  UC2GrC(x2, y2, xf2, yf2);
  mGrC->DrawLine(xf1, yf1, xf2, yf2);

}  


/* --Methode-- */
void PIGraphicUC::DrawBox(PIGrCoord xc, PIGrCoord yc, PIGrCoord dxc, PIGrCoord dyc)
{
  if (!mGrC) return;
  double x, y, dx, dy;
  x = xc;  dx = dxc;
  y = yc;  dy = dyc;
  if (clip) {
    if (dx < 0) {
      x = x+dx;
      dx = -dx;
    }
    if (dy < 0) {
      y = y+dy;
      dy = -dy;
    }
    if (x > xMax || x+dx < xMin || y > yMax || y+dy < yMin) return;
    if (x < xMin) {
      dx -= (xMin-x);
      x = xMin;
    }
    if (y < yMin) {
      dy -= (yMin-y);
      y = yMin;
    }
    if (x+dx > xMax)
      dx = (xMax-x);
    if (y+dy > yMax)
      dy = (yMax-y);
  }

  double xf, yf, xf2, yf2;
  UC2GrC(x, y, xf, yf);
  UC2GrC(x+dx, y+dy, xf2, yf2);
  if (xf2 < xf)  dbl_swap(xf, xf2);
  if (yf2 < yf)  dbl_swap(yf, yf2);
  mGrC->DrawBox(xf, yf, xf2-xf, yf2-yf);
}  

/* --Methode-- */
void PIGraphicUC::DrawFBox(PIGrCoord xc, PIGrCoord yc, PIGrCoord dxc, PIGrCoord dyc)
{
  if (!mGrC) return;
  double x, y, dx, dy;
  x = xc;  dx = dxc;
  y = yc;  dy = dyc;
  if (clip) {
    if (dx < 0) {
      x = x+dx;
      dx = -dx;
    }
    if (dy < 0) {
      y = y+dy;
      dy = -dy;
    }
    if (x > xMax || x+dx < xMin || y > yMax || y+dy < yMin) return;
    if (x < xMin) {
      dx -= (xMin-x);
      x = xMin;
    }
    if (y < yMin) {
      dy -= (yMin-y);
      y = yMin;
    }
    if (x+dx > xMax)
      dx = (xMax-x);
    if (y+dy > yMax)
      dy = (yMax-y);
  }

  double xf, yf, xf2, yf2;
  UC2GrC(x, y, xf, yf);
  UC2GrC(x+dx, y+dy, xf2, yf2);
  if (xf2 < xf)  dbl_swap(xf, xf2);
  if (yf2 < yf)  dbl_swap(yf, yf2);
  mGrC->DrawFBox(xf, yf, xf2-xf, yf2-yf);
}  

/* --Methode-- */
void PIGraphicUC::DrawCircle(PIGrCoord x, PIGrCoord y, PIGrCoord r)
{
  if (!mGrC) return;

  double xf, yf, rf,rfy;
  UC2GrC(x, y, xf, yf);
  DUC2GrC(r,r,rf,rfy);
  rf = 0.5*(rf+rfy);
  mGrC->DrawCircle(xf, yf, rf);
}  

/* --Methode-- */
void PIGraphicUC::DrawFCircle(PIGrCoord x, PIGrCoord y, PIGrCoord r)
{
  if (!mGrC) return;

  double xf, yf, rf, rfy;
  UC2GrC(x, y, xf, yf);
  DUC2GrC(r,r,rf,rfy);
  rf = 0.5*(rf+rfy);
  mGrC->DrawFCircle(xf, yf, rf);
}

/* --Methode-- */
void PIGraphicUC::DrawOval(PIGrCoord x0, PIGrCoord y0, PIGrCoord dx, PIGrCoord dy)
{
  if (!mGrC) return;

  double xf, yf, dxf, dyf;
  UC2GrC(x0, y0, xf, yf);
  DUC2GrC(dx, dy, dxf, dyf);
  mGrC->DrawOval(xf, yf, dxf, dyf);
}

/* --Methode-- */
void PIGraphicUC::DrawFOval(PIGrCoord x0, PIGrCoord y0, PIGrCoord dx, PIGrCoord dy)
{
  if (!mGrC) return;

  double xf, yf, dxf, dyf;
  UC2GrC(x0, y0, xf, yf);
  DUC2GrC(dx, dy, dxf, dyf);
  mGrC->DrawFOval(xf, yf, dxf, dyf);
}

#define NMXMULTP  30   // Pour multipoint sans new

/* --Methode-- */
void PIGraphicUC::DrawPolygon(PIGrCoord *x, PIGrCoord *y, int n, bool cinc)
{
  PIGrCoord xc[NMXMULTP], yc[NMXMULTP];
  PIGrCoord *pxc, *pyc;
  int i;
  double xf, yf;
 
  if (!mGrC) return;
  if (n <= 0)  return;

  if (n > NMXMULTP) { pxc = new PIGrCoord[n];  pyc = new PIGrCoord[n]; }
  else { pxc = xc;  pyc = yc; }
  for(i=0; i<n; i++) {
    UC2GrC(x[i], y[i], xf, yf);
    pxc[i] = xf;  pyc[i] = yf; 
  }
  mGrC->DrawPolygon(pxc, pyc, n, cinc);
  if (n > NMXMULTP) { delete[] pxc;  delete[] pyc; }
  return;
}
  
/* --Methode-- */
void PIGraphicUC::DrawFPolygon(PIGrCoord *x, PIGrCoord *y, int n, bool cinc)
{
  PIGrCoord xc[NMXMULTP], yc[NMXMULTP];
  PIGrCoord *pxc, *pyc;
  int i;
  double xf, yf;
 
  if (!mGrC) return;
  if (n <= 0)  return;

  if (n > NMXMULTP) { pxc = new PIGrCoord[n];  pyc = new PIGrCoord[n]; }
  else { pxc = xc;  pyc = yc; }
  for(i=0; i<n; i++) {
    UC2GrC(x[i], y[i], xf, yf);
    pxc[i] = xf;  pyc[i] = yf; 
  }
  mGrC->DrawFPolygon(pxc, pyc, n, cinc);
  if (n > NMXMULTP) { delete[] pxc;  delete[] pyc; }
  return;
}


/* --Methode-- */
void PIGraphicUC::DrawArc(PIGrCoord x0, PIGrCoord y0, PIGrCoord dx, PIGrCoord dy,
                          double degdeb, double deltadeg)
{
  if (!mGrC) return;

  double xf, yf, dxf, dyf;
  UC2GrC(x0, y0, xf, yf);
  DUC2GrC(dx, dy, dxf, dyf);
  // $CHECK$ - Reza Nov 2002 , Il faudra aussi tenir compte de l'axe X
  if (!isAxeYDirUpDown()) degdeb = 360.-(degdeb+deltadeg);
  mGrC->DrawArc(xf, yf, dxf, dyf, degdeb, deltadeg);
}
/* --Methode-- */
void PIGraphicUC::DrawFArc(PIGrCoord x0, PIGrCoord y0, PIGrCoord dx, PIGrCoord dy,
                           double degdeb, double deltadeg)
{
  if (!mGrC) return;

  double xf, yf, dxf, dyf;
  UC2GrC(x0, y0, xf, yf);
  DUC2GrC(dx, dy, dxf, dyf);
  // $CHECK$ - Reza Nov 2002 , Il faudra aussi tenir compte de l'axe X
  if (!isAxeYDirUpDown()) degdeb = 360.-(degdeb+deltadeg);
  mGrC->DrawFArc(xf, yf, dxf, dyf, degdeb, deltadeg);
}

/* --Methode-- */
void PIGraphicUC::Draw3PtArc(PIGrCoord x1, PIGrCoord y1, PIGrCoord x2, PIGrCoord y2,
			     PIGrCoord x3, PIGrCoord y3)
  // Trace d'un arc de cercle passant par 3 points
{
  if (!mGrC) return;
  double xf1, xf2, xf3;
  double yf1, yf2, yf3;
  UC2GrC(x1, y1, xf1, yf1);
  UC2GrC(x2, y2, xf2, yf2);
  UC2GrC(x3, y3, xf3, yf3);
  mGrC->Draw3PtArc(xf1, yf1, xf2, yf2, xf3, yf3);
}

/* --Methode-- */
void PIGraphicUC::Draw3PtFArc(PIGrCoord x1, PIGrCoord y1, PIGrCoord x2, PIGrCoord y2,
			      PIGrCoord x3, PIGrCoord y3)
  // Trace d'un arc de cercle passant par 3 points
{
  if (!mGrC) return;
  double xf1, xf2, xf3;
  double yf1, yf2, yf3;
  UC2GrC(x1, y1, xf1, yf1);
  UC2GrC(x2, y2, xf2, yf2);
  UC2GrC(x3, y3, xf3, yf3);
  mGrC->Draw3PtFArc(xf1, yf1, xf2, yf2, xf3, yf3);
}


/* --Methode-- */
void PIGraphicUC::DrawMarker(PIGrCoord x0, PIGrCoord y0)
{
  if (!mGrC) return;
  double xf, yf;
  UC2GrC(x0, y0, xf, yf);
  mGrC->DrawMarker(xf, yf);
  return;
}

/* --Methode-- */
void PIGraphicUC::DrawMarkers(PIGrCoord *x, PIGrCoord *y, int n)
{
  PIGrCoord xc[NMXMULTP], yc[NMXMULTP];
  PIGrCoord *pxc, *pyc;
  int i;
  double xf, yf;
 
  if (!mGrC) return;
  if (n <= 0)  return;

  if (n > NMXMULTP) { pxc = new PIGrCoord[n];  pyc = new PIGrCoord[n]; }
  else { pxc = xc;  pyc = yc; }
  for(i=0; i<n; i++) {
    UC2GrC(x[i], y[i], xf, yf);
    pxc[i] = xf;  pyc[i] = yf; 
  }
  mGrC->DrawMarkers(pxc, pyc, n);
  if (n > NMXMULTP) { delete[] pxc;  delete[] pyc; }
  return;
}

/* --Methode-- */
void PIGraphicUC::DrawArrowMarker(PIGrCoord x1, PIGrCoord y1, PIGrCoord x2, PIGrCoord y2, bool fgline)
{
  if (!mGrC) return;
  double xf1, yf1, xf2, yf2;
  UC2GrC(x1, y1, xf1, yf1);
  UC2GrC(x2, y2, xf2, yf2);
  mGrC->DrawArrowMarker(xf1, yf1, xf2, yf2, fgline);
}

/* --Methode-- */
void PIGraphicUC::DrawPixmap(PIGrCoord x, PIGrCoord y, unsigned char *pix,
                        int sx, int sy, PIColorMap* cmap)
{
  if (!mGrC) return;
  if ( (sx < 1) || (sy < 1) )  return;
  if ((pix == NULL) || (cmap == NULL)) return; 
  double xf,yf;
  UC2GrC(x, y, xf, yf);
  mGrC->DrawPixmap(xf, yf, pix, sx, sy, cmap);
}



/* --Methode-- */
void PIGraphicUC::SelForeground(PIColors col)
{
  if (!mGrC) return;
  if (myLockFCol)  return;  
  mGrC->SelForeground(col);
  return;  
}


/* --Methode-- */
void PIGraphicUC::SelBackground(PIColors col)
{
  if (!mGrC) return;
  mGrC->SelBackground(col);
  return;  
}

/* --Methode-- */
void PIGraphicUC::SelForeground(PIColorMap& cmap, int cid)
{
  if (!mGrC) return;
  mGrC->SelForeground(cmap, cid);
  return;  
}


/* --Methode-- */
void PIGraphicUC::SelBackground(PIColorMap& cmap, int cid)
{
  if (!mGrC) return;
  mGrC->SelBackground(cmap, cid);
  return;  
}

/* --Methode-- */
void PIGraphicUC::SelGOMode(PIGOMode mod)
{
  if (!mGrC) return;
  mGrC->SelGOMode(mod);
  return;  
}

/* --Methode-- */
void PIGraphicUC::SelFont(PIFont & fnt)
{
  if (!mGrC) return;
  mGrC->SelFont(fnt);
  myFont = mGrC->GetFont();
  return;  
}

/* --Methode-- */
void PIGraphicUC::SelFont(PIFontSize sz, PIFontAtt att)
{
  if (!mGrC) return;
  mGrC->SelFont(sz, att);
  myFont = mGrC->GetFont();
  return;  
}

/* --Methode-- */
void PIGraphicUC::SelFontSzPt(int npt, PIFontAtt att)
{
  if (!mGrC) return;
  mGrC->SelFontSzPt(npt, att);
  myFont = mGrC->GetFont();
  return;  
}


/* --Methode-- */
void PIGraphicUC::SelLine(PILineAtt const& att)
{
  if (!mGrC) return;
  mGrC->SelLine(att);
  return;  
}

/* --Methode-- */
void PIGraphicUC::SelMarker(int msz, PIMarker mrk)
{
  if (!mGrC) return;
  mGrC->SelMarker( msz, mrk);
}

/* --Methode-- */
void PIGraphicUC::SelArrowMarker(int arrsz, PIArrowMarker arrmrk)
{
  if (!mGrC) return;
  mGrC->SelArrowMarker(arrsz, arrmrk);
}

/* --Methode-- */
void PIGraphicUC::SelFontSz(PIGrCoord sz)
{
  if (!mGrC) return;
  SelFontSz(sz, mGrC->GetFont().GetFontAtt());
}

/* --Methode-- */
void PIGraphicUC::SelFontSz(PIGrCoord sz, PIFontAtt att)
{
  if (!mGrC) return;
  double fx, fy;
  DUC2GrC((double)sz, (double)sz, fx, fy);
  int npt = (int)fy;
  if (npt < 6) npt = 6;
  if (npt > 127) npt = 127;
  mGrC->SelFontSzPt(npt, att);
  myFont = mGrC->GetFont();
}


/* --Methode-- */
void PIGraphicUC::SelMarkerSz(PIGrCoord sz, PIMarker mrk)
{
  if (!mGrC) return;
  double fx, fy;
  DUC2GrC((double)sz, (double)sz, fx, fy);
  int isz = int(0.5*(fx+fy+1));
  mGrC->SelMarker( isz, mrk);
}

/* --Methode-- */
void PIGraphicUC::SelArrowMarkerSz(PIGrCoord arrsz, PIArrowMarker arrmrk)
{
  if (!mGrC) return;
  double fx, fy;
  DUC2GrC((double)arrsz, (double)arrsz, fx, fy);
  int asz = int(fy+0.5);
  if (asz < 3) asz = 3;
  if (asz > 127) asz = 127;
  mGrC->SelArrowMarker(asz, arrmrk);
}

/* --Methode-- */
void PIGraphicUC::SetClipRectangle(PIGrCoord x0, PIGrCoord y0, PIGrCoord dx, PIGrCoord dy)
{
  /* $CHECK$  A faire Reza 08/02/97  */
return;
}
/* --Methode-- */
void PIGraphicUC::ClearClipRectangle()
{
  /* $CHECK$  A faire Reza 08/02/97  */
return;
}

/* --Methode-- */
PIColors PIGraphicUC::GetForeground()
{
  if (!mGrC) return(PI_NotDefColor);
  return(mGrC->GetForeground());
}

/* --Methode-- */
PIColors PIGraphicUC::GetBackground()
{
  if (!mGrC) return(PI_NotDefColor);
  return(mGrC->GetBackground());
}

/* --Methode-- */
PIGOMode PIGraphicUC::GetGOMode()
{
  if (!mGrC) return(PI_GOCopy);
  return(mGrC->GetGOMode());
}


/* --Methode-- */
PILineAtt PIGraphicUC::GetLineAtt()
{
  if (!mGrC) return(PI_NotDefLineAtt);
  return(mGrC->GetLineAtt());
}

/* --Methode-- */
PIMarker PIGraphicUC::GetMarker()
{
  if (!mGrC) return(PI_NotDefMarker);
  return(mGrC->GetMarker());
}

/* --Methode-- */
int PIGraphicUC::GetMarkerSize()
{
  if (!mGrC) return(0);
  return(mGrC->GetMarkerSize());
}

/* --Methode-- */
PIArrowMarker PIGraphicUC::GetArrowMarker()
{
  if (!mGrC) return(PI_NotDefArrowMarker);
  return(mGrC->GetArrowMarker());
}

/* --Methode-- */
int PIGraphicUC::GetArrowMarkerSize()
{
  if (!mGrC) return(0);
  return(mGrC->GetArrowMarkerSize());
}


/* --Methode-- */
PIGrCoord PIGraphicUC::GetFontHeight(PIGrCoord& asc, PIGrCoord& desc)
{
  asc = desc = 0;
  if (!mGrC) return(0);
  int h,a,d;
  double fh, fa, fd, x;
  h = myFont.GetFontHeight(a, d) ;
  DGrC2UC(0., h, x, fh);
  DGrC2UC(0., a, x, fa);
  DGrC2UC(0., d, x, fd);
  asc = a;  desc = d;
  return(fh);
}


/* --Methode-- */
PIGrCoord PIGraphicUC::CalcStringWidth(char const* s)
{
  if (!mGrC) return(0.);
  double dx = myFont.GetStringWidth(s);
  double dxx, dxy;
  DGrC2UC(dx, dx, dxx, dxy);
  return(dxx);
}


/* --Methode-- */
void PIGraphicUC::SaveGraphicAtt()
{
  if (!mGrC) return;
  mGrC->SaveGraphicAtt();
}

/* --Methode-- */
void PIGraphicUC::RestoreGraphicAtt()
{
  if (!mGrC) return;
  mGrC->RestoreGraphicAtt();
}

