// Module PI : Peida Interactive PIDrawer3D PIDraw3DWdg
// Drawer et DrawWidget 3D       R. Ansari 06/98
// LAL (Orsay) / IN2P3-CNRS  DAPNIA/SPP (Saclay) / CEA

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#include "pi3ddrw.h"
#include "pidrwtools.h"


// ......................................................................
// ........................  Classe PIDrawer3D ..........................
// ......................................................................
//++
// Class	PIDrawer3D
// Lib		PI
// include	pidrawer.h
//
//	Classe pour la création d'objets, capables de produire
//	un dessin 3D dans une composante graphique.
//--
//++
// Links	Parent
// PIDrawer
//--
//++
// Links	Voir aussi
// PIGraphic3D
// PIDraw3DWdg
//--

//++
// Titre	Constructeur, méthodes
//--
//++
// PIDrawer3D()
//	Cosntructeur
// void Set3DView_Obs(double xo, double yo, double zo, double teta, double phi, double psi, -
//               double dax, double day, double co, double dco=0.2)
//	Définition de la vue 3D. Voir "PIGraphic3D::Set3DCS_Obs(...)"
// void Set3DView(double xc, double yc, double zc, double xo, double yo, double zo, -
//                double dax, double day, double dco=0.2, double psi=0.)
//	Définition de la vue 3D. Voir "PIGraphic3D::Set3DCS(...)"
// bool Get3DView(double& xc, double& yc, double& zc, double& xo, double& yo, double& zo, -
//                double& teta, double& phi, double& psi, double& dax, double& day, double& co, double& dco)
//	Renvoie la définition de la Vue-3D. Retourne "true " si définie par "Set3DView_Obs()"
// void Draw3DBoxe(PIGraphic3D* g3, double xx1, double xx2, double yy1, double yy2,  -
//                 double zz1, double zz2, double xl1, double xl2, -
//                 double yl1, double yl2, double zl1, double zl2)
//	Trace une boîte avec les coordonnées matérialisant la vue 3D.
//--

/* --Methode-- */
PIDrawer3D::PIDrawer3D()
        : PIDrawer()
{
  xO = yO = 0.; zO = -10.;
  xC = yC = zC = 0.;
  tO = fO = pO = 0.; 
  daxO = dayO = 0.25;
  lCO = 10.;  dlCO = 3.;  
  v3D_obs = false;
  x3Min = y3Min = z3Min = -1.;  
  x3Max = y3Max = z3Max = 1.;
}

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

/* --Methode-- */
void PIDrawer3D::Set3DView_Obs(double xo, double yo, double zo, double teta, double phi, double psi, 
                               double dax, double day, double co, double dco)
{
  tO = teta;  fO = phi;  pO = psi;
  daxO = dax;  dayO = day;
  lCO = co;   dlCO = dco;
  v3D_obs = true;
}

/* --Methode-- */
void PIDrawer3D::Set3DView(double xc, double yc, double zc, double xo, double yo, double zo, 
                           double dax, double day, double dco, double psi)
{
  xC = xc;  yC = yc;  zC = zc;
  xO = xo;  yO = yo;  zO = zo;
  pO = psi;
  daxO = dax;  dayO = day;
  dlCO = dco;
  v3D_obs = false;
}

/* --Methode-- */
bool PIDrawer3D::Get3DView(double& xc, double& yc, double& zc, double& xo, double& yo, double& zo,
                           double& teta, double& phi, double& psi, double& dax, double& day, double& co, double& dco)
{
  xo = xO;  yo = yO;  zo = zO;
  xc = xC;  yc = yC;  zc = zC;
  teta = tO;  phi = fO;  psi = pO;
  dax = daxO;   day = dayO;
  co = lCO;     dco = dlCO;
  return(v3D_obs);
}

/* --Methode-- */
PIGraphicUC* PIDrawer3D::SetDrwWdg(PIBaseWdgGen* drw, int x0, int y0, int dx, int dy, PIGraphicGen* g)
{
  mBWdg = drw;
  xW0 = x0;   yW0 = y0;
  xWd = dx;   yWd = dy;
  if (mGrUC)  delete mGrUC;
  PIGraphic3D* gr3d;
  gr3d = new PIGraphic3D(g, x0, y0, dx, dy);
  if (v3D_obs)  gr3d->Set3DCS_Obs(xO, yO, zO, tO, fO, pO, daxO, dayO, lCO, dlCO);
  else  gr3d->Set3DCS(xC,yC,zC, xO, yO, zO, daxO, dayO, dlCO, pO);
  if (mFgHighLight) gr3d->SelGOMode(PI_GOInvert);  // $CHECK$ A changer , Reza 07/2001
  mGrUC = gr3d;
  return(gr3d); 
}

/* --Methode-- */
void PIDrawer3D::DrawAxes(PIGraphicUC* g)
{
  if (axesFlags == kAxesNone) return;
#if defined(CC_HAS_RTTI_SUPPORT)
  PIGraphic3D* g3 = dynamic_cast<PIGraphic3D*>(g);
#else
  PIGraphic3D* g3 = (PIGraphic3D*)(g);
#endif
  Draw3DBoxe(g3, XMin3(), XMax3(), YMin3(), YMax3(), ZMin3(), ZMax3(),
                 XMin3(), XMax3(), YMin3(), YMax3(), ZMin3(), ZMax3());  
}

/* --Methode-- */
void PIDrawer3D::Draw3DBoxe(PIGraphic3D* g3, 
                            double xx1, double xx2, double yy1, double yy2, 
                            double zz1, double zz2, double xl1, double xl2, 
                            double yl1, double yl2, double zl1, double zl2)
{
  if (mLAtt == PI_NotDefLineAtt)    g3->SelLine(PI_ThinLine);
  if (mFSz == PI_NotDefFontSize)    g3->SelFontSz((YMax()-YMin())/150.);

  PIGrCoord x1,y1,z1,x2,y2,z2;
  char strg[64];
  int k;
  int NTicks = 5;  // Nb de ticks sur chaque axe

  x1 = xx1;  y1 = yy1;  z1 = zz1;
  x2 = xx2;   y2 = yy1;   z2 = zz1; 
  g3->DrawLine3D(x1, y1, z1, x2, y2, z2);
  y1 = y2 = yy2;
  g3->DrawLine3D(x1, y1, z1, x2, y2, z2);
  z1 = z2 = zz2;
  g3->DrawLine3D(x1, y1, z1, x2, y2, z2);
  y1 = y2 = yy1;  
  g3->DrawLine3D(x1, y1, z1, x2, y2, z2);

// Trace des ticks et labels axe X :
  x1 = x2 = xx1;   y1 = y2 = yy1;  z1 = z2 = zz1;
  for (k=0; k<NTicks; k++) {
    x1 = x2 = (xx1+(double)k*(xx2-xx1)/(NTicks-1.));
    z1 = zz1; z2 = zz1-0.02*(zz2-zz1);
    y1 = y2 = yy1;
    g3->DrawLine3D(x1, y1, z1, x2, y2, z2);
    z2 = zz1-0.05*(zz2-zz1); 
    y2 = yy1-0.075*(yy2-yy1);  
    sprintf(strg,"%.2g", xl1+(double)k*(xl2-xl1)/(NTicks-1.));
    g3->DrawString3D(x2, y2, z2, strg);
    }
  x2 = xx2+0.075*(xx2-xx1);  y2 = yy1;   z2 = zz1-0.05*(zz2-zz1); 
  g3->DrawString3D(x2, y2, z2, "X");

  x1 = xx1;  y1 = yy1;  z1 = zz1;
  x2 = xx1;   y2 = yy2;   z2 = zz1; 
  g3->DrawLine3D(x1, y1, z1, x2, y2, z2);
  x1 = x2 = xx2;
  g3->DrawLine3D(x1, y1, z1, x2, y2, z2);
  z1 = z2 = zz2;
  g3->DrawLine3D(x1, y1, z1, x2, y2, z2);
  x1 = x2 = xx1;  
  g3->DrawLine3D(x1, y1, z1, x2, y2, z2);
  x1 = x2 = xx2;   y1 = y2 = yy1;  z1 = z2 = zz1;
  for (k=1; k<NTicks; k++) {   // Attention, par le tick 0 pour Y
    y1 = y2 = (yy1+(double)k*(yy2-yy1)/(NTicks-1.));
    z2 = zz1-0.02*(zz2-zz1);
    x1 = x2 = xx2; 
    g3->DrawLine3D(x1, y1, z1, x2, y2, z2);
    z2 = zz1-0.05*(zz2-zz1); 
    x2 = xx2+0.075*(xx2-xx1);  
    sprintf(strg,"%.2g", yl1+(double)k*(yl2-yl1)/(NTicks-1.));
    g3->DrawString3D(x2, y2, z2, strg);
    }
  x2 = xx2;  y2 = yy2+0.075*(yy2-yy1);   z2 = zz1-0.05*(zz2-zz1); 
  g3->DrawString3D(x2, y2, z2, "Y");

  x1 = xx1;  y1 = yy1;  z1 = zz1;
  x2 = xx1;   y2 = yy1;   z2 = zz2; 
  g3->DrawLine3D(x1, y1, z1, x2, y2, z2);
  x1 = x2 = xx2;
  g3->DrawLine3D(x1, y1, z1, x2, y2, z2);
  y1 = y2 = yy2;
  g3->DrawLine3D(x1, y1, z1, x2, y2, z2);
  x1 = x2 = xx1;  
  g3->DrawLine3D(x1, y1, z1, x2, y2, z2);
  x1 = x2 = xx1;   y1 = y2 = yy1;  z1 = z2 = zz1;
  for (k=0; k<NTicks; k++) {
    z1 = z2 = (zz1+(double)k*(zz2-zz1)/(NTicks-1.));
    y2 = yy1-0.015*(yy2-yy1);
    x2 = xx1-0.015*(xx2-xx1);
    g3->DrawLine3D(x1, y1, z1, x2, y2, z2);
    x2 = xx1-0.1*(xx2-xx1);  
    y2 = yy1-0.1*(yy2-yy1);  
    sprintf(strg,"%.2g", zl1+(double)k*(zl2-zl1)/(NTicks-1.));
    g3->DrawString3D(x2, y2, z2, strg);
    }
  x2 = xx1-0.075*(xx2-xx1);  y2 = yy1-0.075*(yy2-yy1);   z2 = zz2+0.05*(zz2-zz1); 
  g3->DrawString3D(x2, y2, z2, "Z");

}

// ......................................................................
// .......................  Classe PIDraw3DWdg ..........................
// ......................................................................

//++
// Class	PIDraw3DWdg
// Lib		PI
// include	pi3ddrw.h
//
//   	Classe pour la l'affichage et la manipulation d'un ensemble
//	de *Drawer3D* avec la gestion de zoom, rotation, déplacement
//	d'objet.
//	* Bouton-1 : Envoie le message "PIMsg_Active".
//	* Bouton-2 : Permet de faire tourner l'observateur (caméra) 
//	autour de l'objet.
//	* Shift-Bouton-2 : Permet de tourner l'objet en maintenant 
//	la caméra fixe. Cette fonction peut-être réalisée sans le shift
//	à partir du centre de l'objet, en l'ayant préalablement activée
//	par <Alt>S.
//	* Bouton-3 : Gestion de zoom (On approche/ éloigne la caméra, ou 
//	on change l'angle d'ouverture) 
//
//	Gestion du clavier :
//	* <Alt>G : Affichage d'une fenêtre de changement des attributs graphiques
//	* <Alt>O : Action identique a <Alt>G
//	* <Alt>V : Copier/*Coller* Ajout du texte du buffer copier/coller
//	sur l'objet à la position courante de la souris
//	* <Alt>Z : Supprime les textes et signes ajoutés au dessin.
//	* <Alt>A : Active/desactive l'affichage des axes
//	* <Alt>R : Reinitialise la vue 3D (vue par défaut) et rafraichit le dessin.
//	* <Alt>S : Active/desactive le mode de rotation d'objet sans Shift
//
//--
//++
// Links	Parents
// PIBaseWdg
//--
//++
// Links	Voir aussi
// PIDrawer3D
//--

//++
// Titre	Constructeur, méthodes
//--
//++
// PIDraw3DWdg(PIContainerGen *par, const char *nom, int sx=100, int sy=100, int px=0, int py=0)
//	Constructeur
// long	 kind()
//	Renvoie le type de l'objet ("=PIDraw3DWdg::ClassId")
// int AddDrawer3D(PIDrawer3D*, bool ad=false)
//	Ajoute un Drawer3D
//--

/* --Methode-- */
PIDraw3DWdg::PIDraw3DWdg(PIContainerGen *par, const char *nom, int sx, int sy, int px, int py)
        : PIBaseWdg(par, nom, sx, sy, px, py)
{  
  vfixed = false;
//  SetDefaultDrawRectangle(0.12, 0.12, 0.88, 0.88, true);
  SetDefaultDrawRectangle(0., 0., 1., 1., true);
  mBDrw = new PIElDrawer;
  mBDrw->SetLimits(0.12,0.88, 0.12,0.88, kAxeDirLtoR,kAxeDirDownUp);
  AddDrawer(mBDrw, 0.12, 0.12, 0.88, 0.88, true, false, false);
  mPx = mPy = 0;

  lPx = lPy = 0;
  lCol = PI_Black;
  cTeta = cPhi = 0.;  cUlen = 1.;

  ActivateKeyboard();
  ActivateButton(2);    //  Pour pouvoir tourner la camera
  ActivateMove(2);      
  ActivateButton(3);    //  Pour deplacer la camera le long de son axe
  ActivateMove(3);
  ActivateButton(1);    

  mGr3d = new PIGraphic3D(mWGrC, 0, 0, sx, sy);
  rOfg = false;
  axfg = true;
  skcfg = false;
}

/* --Methode-- */
PIDraw3DWdg::~PIDraw3DWdg()
{
  delete mBDrw;
  delete mGr3d;
}

/* --Methode-- */
void PIDraw3DWdg::Set3DView_Obs(double xo, double yo, double zo, double teta, double phi, double psi, 
                                double dax, double day, double co, double dco)
{
  mGr3d->Set3DCS_Obs(xo, yo, zo, teta, phi, psi, dax, day, co, dco);
  list<int>::iterator it;
  for(it = m3DrIl.begin(); it != m3DrIl.end(); it++)   
#if defined(CC_HAS_RTTI_SUPPORT)
    (dynamic_cast<PIDrawer3D*>(GetDrawerId(*it)))->Set3DView_Obs(xo, yo, zo, teta, phi, psi, dax, day, co, dco);
#else
    ((PIDrawer3D*)(GetDrawerId(*it)))->Set3DView_Obs(xo, yo, zo, teta, phi, psi, dax, day, co, dco);
#endif
  vfixed = true;
}

/* --Methode-- */
void PIDraw3DWdg::Set3DView(double xc, double yc, double zc, double xo, double yo, double zo, 
                            double dax, double day, double dco, double psi)
{
  mGr3d->Set3DCS(xc, yc, zc, xo, yo, zo, dax, day, dco, psi);
  list<int>::iterator it;
  for(it = m3DrIl.begin(); it != m3DrIl.end(); it++)   
#if defined(CC_HAS_RTTI_SUPPORT)
    (dynamic_cast<PIDrawer3D*>(GetDrawerId(*it)))->Set3DView(xc, yc, zc, xo, yo, zo, dax, day, dco, psi);
#else
    ((PIDrawer3D*)(GetDrawerId(*it)))->Set3DView(xc, yc, zc, xo, yo, zo, dax, day, dco, psi);
#endif
  vfixed = true;
}

/* --Methode-- */
bool PIDraw3DWdg::Get3DView(double& xc, double& yc, double& zc, double& xo, double& yo, double& zo, 
                            double& teta, double& phi, double& psi, double& dax, double& day, double& co, double& dco)
{
  return(mGr3d->Get3DCS(xc, yc, zc, xo, yo, zo, teta, phi, psi, dax, day, co, dco));
}


/* --Methode-- */
void PIDraw3DWdg::Update3DView()
{
  list<int>::iterator it = m3DrIl.begin();
  if (it == m3DrIl.end())  return;
#if defined(CC_HAS_RTTI_SUPPORT)
  PIDrawer3D* dr3 = dynamic_cast<PIDrawer3D*>(GetDrawerId(*it));
#else
  PIDrawer3D* dr3 = (PIDrawer3D*)(GetDrawerId(*it));
#endif
  if (dr3 == NULL)  return;
  dr3->UpdateLimits();
  double xo, yo, zo, xc, yc, zc, teta, phi, psi, dax, day, co, dco;
  bool vobs;
  vobs = dr3->Get3DView(xc, yc, zc, xo, yo, zo, teta, phi, psi, dax, day, co, dco);
  if (vobs) Set3DView_Obs(xo, yo, zo, teta, phi, psi, dax, day, co, dco);
  else Set3DView(xc, yc, zc, xo, yo, zo, dax, day, dco, psi);
  Refresh();
}


/* --Methode-- */
void PIDraw3DWdg::SetDrawers3DView()
{
  double xc, yc, zc, xo, yo, zo;
  double teta, phi, psi;
  double dax, day, co, dco;
  bool vo;
  vo = mGr3d->Get3DCS( xc, yc, zc, xo, yo, zo, teta, phi, psi, dax, day, co, dco);
  list<int>::iterator it;

#if defined(CC_HAS_RTTI_SUPPORT)
  if (vo)   for(it = m3DrIl.begin(); it != m3DrIl.end(); it++)   
    (dynamic_cast<PIDrawer3D*>(GetDrawerId(*it)))->Set3DView_Obs(xo, yo, zo, teta, phi, psi, dax, day, co, dco);
  else   for(it = m3DrIl.begin(); it != m3DrIl.end(); it++)   
    (dynamic_cast<PIDrawer3D*>(GetDrawerId(*it)))->Set3DView(xc, yc, zc, xo, yo, zo, dax, day, dco, psi);    
#else
  if (vo)   for(it = m3DrIl.begin(); it != m3DrIl.end(); it++)   
    ((PIDrawer3D*)(GetDrawerId(*it)))->Set3DView_Obs(xo, yo, zo, teta, phi, psi, dax, day, co, dco);
  else   for(it = m3DrIl.begin(); it != m3DrIl.end(); it++)   
    ((PIDrawer3D*)(GetDrawerId(*it)))->Set3DView(xc, yc, zc, xo, yo, zo, dax, day, dco, psi);    
#endif

}

/* --Methode-- */
int PIDraw3DWdg::AddDrawer3D(PIDrawer3D* dr3, bool ad)
{
if (!vfixed)  { 
  dr3->UpdateLimits();
  double xo, yo, zo, xc, yc, zc, teta, phi, psi, dax, day, co, dco;
  bool vobs;
  vobs = dr3->Get3DView(xc, yc, zc, xo, yo, zo, teta, phi, psi, dax, day, co, dco);
  if (vobs) Set3DView_Obs(xo, yo, zo, teta, phi, psi, dax, day, co, dco);
  else Set3DView(xc, yc, zc, xo, yo, zo, dax, day, dco, psi);
  }
else { 
  double xc, yc, zc, xo, yo, zo, teta, phi, psi, dax, day, co, dco;
  if ( Get3DView(xc, yc, zc, xo, yo, zo, teta, phi, psi, dax, day, co, dco) ) 
      dr3->Set3DView_Obs(xo, yo, zo, teta, phi, psi, dax, day, co, dco);
  else  dr3->Set3DView(xc, yc, zc, xo, yo, zo, dax, day, co, psi);
  }
int id = AddDrawer(dr3, false, false, ad);
if (m3DrIl.size() == 0)  dr3->SetAxesFlags(kStdAxes);
else dr3->SetAxesFlags(kAxesNone);
m3DrIl.push_back(id);
return(id);
}

/* --Methode-- */
void PIDraw3DWdg::RemoveDrawer(int id)
{
  list<int>::iterator it;
  for(it = m3DrIl.begin(); it != m3DrIl.end(); it++)   
    if ( (*it) == id )  { m3DrIl.erase(it);  break; }
  PIBaseWdg::RemoveDrawer(id);
}

/* --Methode-- */
void PIDraw3DWdg::DeleteDrawers()
{
  m3DrIl.erase(m3DrIl.begin(),  m3DrIl.end());
  PIBaseWdg::DeleteDrawers();
}

/* --Methode-- */
void PIDraw3DWdg::Keyboard(int key, PIKeyModifier kmod)
{
if (kmod == PIKM_Alt) {
  if (key == 'V' || key == 'v') RequestSelection();  // Pour coller (copier/coller)  
  if (key == 'Z' || key == 'z') { mBDrw->ElDelAll();  Refresh(); } // Pour supprimer tous les signes 
  if (key == 'O' || key == 'o' || key == 'G' || key == 'g') { 
    PIDrwTools::SetCurrentBaseWdg(this);
    PIDrwTools::ShowPIDrwTools();   // Fentre axes et options de trace
    }
  if (key == 'A' || key == 'a')  {    // On affiche ou on enleve les axes
    axfg = !axfg;
    list<int>::iterator it;
    if (axfg) 
      for(it = m3DrIl.begin(); it != m3DrIl.end(); it++)  
         GetDrawerId(*it)->SetAxesFlags(kAxesNone);
    else { 
      it = m3DrIl.begin(); 
      if (it != m3DrIl.end())  GetDrawerId(*it)->SetAxesFlags(kStdAxes);
      }
    Refresh(); 
    }
//  <Alt>S active la sensibilite de la zone centrale pour tourner l'objet
  if (key == 'S' || key == 's')  skcfg = !skcfg;  
  if (key == 'R' || key == 'r')  Update3DView();
  }
}

/* --Methode-- */
void PIDraw3DWdg::PasteSelection(unsigned int typ, void *pdata, unsigned int l)
{
if (typ != PICP_string) return;
int ll = (l<256) ? l+1 : 256;
char pc[256];
strncpy(pc, (char*)pdata, ll-1);  pc[ll-1] = '\0';
// printf("PIDraw3DWdg::PasteSelection() / Debug  %s - %d %d -> %g %g \n", pc, 
//        mPx, mPy, (double)mPx/(double)XSize(), 1.-(double)mPy/(double)YSize());
mBDrw->ElAddText((double)mPx/(double)XSize(), 1.-(double)mPy/(double)YSize(), pc );
mBDrw->Refresh();
}

/* --Methode-- */
void PIDraw3DWdg::But2Press(int x, int y)
{
  mGr3d->SetBaseGraphic(mWGrC, 0, 0, XSize(), YSize());
  double xo, yo, zo;
  double teta, phi, psi;
  double dax, day, co, dco;
  mGr3d->Get3DCS(cXc, cYc, cZc, xo, yo, zo, teta, phi, psi, dax, day, co, dco);
//   puts("\n PIDraw3DWdg::But2Press() ");
//   mGr3d->PrintCS();
  lPx = x;  lPy = y;

// Pour savoir si on se trouve ds la zone centrale   
  int czx = XSize()/10;
  int czy = YSize()/10;
  PIKeyModifier kmod;
  unsigned long tm;
  GetLastEventInfo(kmod, tm);
  rOfg = false;
  if (kmod ==  PIKM_Shift)  rOfg = true;
  else if (skcfg) {
    int dmix = x-XSize()/2;
    int dmiy = y-YSize()/2;
    if (dmix < 0) dmix = -dmix;
    if (dmiy < 0) dmiy = -dmiy;
    if ((dmix < czx) && (dmiy < czy))  rOfg = true;
    }

  cUlen = 0.5*(dax+day)*co*0.3;    cDax = dax;   cDay = day;  clCO = co; 
  cTeta = teta;   cPhi = phi;
  SelPointerShape(PI_TDLRArrowPointer);
  lCol = mWGrC->GetForeground();
  //  mWGrC->SelForeground(GetBackgroundColor());
  mWGrC->SelForeground(PI_Magenta);
/*
  {
  char buff[256];
  sprintf(buff, "But2Press() C=%g %g %g  T,P=%g %g   ", xc, yc, zc, cTeta, cPhi); 
  mWGrC->DrawOpaqueString(0,20,buff);
  }
*/
  DrawXYZAxes();
  if (rOfg)  { czx /= 2;   czy /= 2;  mWGrC->DrawBox(XSize()/2-czx, YSize()/2-czy, czx*2, czy*2); }
 
  Send(Msg(), PIMsg_Active);
  PIDrwTools::SetCurrentBaseWdg(this);
}

/* --Methode-- */
void PIDraw3DWdg::Ptr2Move(int x, int y)
{
  DrawXYZAxes();
  double teta, phi;

  if (rOfg) { 
    phi = cPhi + (M_PI*0.25*(double)(x-lPx)/XSize());
    teta = cTeta - (M_PI*0.25*(double)(y-lPy)/YSize());
    mGr3d->RotateObject(teta, phi, false);
    }
  else {
    phi = cPhi - (M_PI*0.5*(double)(x-lPx)/XSize());
    teta = cTeta + (M_PI*0.5*(double)(y-lPy)/YSize());
    mGr3d->RotateObserver(teta, phi, 0., false);
    }
/*  {
  char buff[256];
  sprintf(buff, "Ptr2Move() T,P=%g %g -> %g %g  ", cTeta, cPhi, teta, phi); 
  mWGrC->DrawOpaqueString(0,20,buff);
  }
*/
  DrawXYZAxes();
}


/* --Methode-- */
void PIDraw3DWdg::But2Release(int x, int y)
{
  DrawXYZAxes();
  if (rOfg) {
    int czx = XSize()/20;
    int czy = YSize()/20;
    mWGrC->DrawBox(XSize()/2-czx, YSize()/2-czy, czx*2, czy*2);
    }

//  puts("\n PIDraw3DWdg::But2Release()");
//  mGr3d->PrintCS();
  SelPointerShape(PI_ArrowPointer);
  mWGrC->SelForeground(lCol);
  SetDrawers3DView();
  Refresh();
}


/* --Methode-- */
void PIDraw3DWdg::But3Press(int x, int y)
{
  double xo, yo, zo;
  double teta, phi, psi;
  double dax, day, co, dco;
  mGr3d->Get3DCS(cXc, cYc, cZc, xo, yo, zo, teta, phi, psi, dax, day, co, dco);
  mGr3d->SetBaseGraphic(mWGrC, 0, 0, XSize(), YSize());
  lPx = x;  lPy = y;  
  cUlen = 0.5*(dax+day)*co*0.3;    cDax = dax;   cDay = day;  clCO = co;
  cTeta = teta;   cPhi = phi;
  SelPointerShape(PI_TDLRArrowPointer);
  lCol = mWGrC->GetForeground();
  //  mWGrC->SelForeground(GetBackgroundColor());
  mWGrC->SelForeground(PI_Magenta);
/*
  {
  char buff[256];
  sprintf(buff, "But3Press() C=%g %g %g  O= %g %g %g  L= %g   ", xc, yc, zc, xo, yo, zo, co); 
  mWGrC->DrawOpaqueString(0,20,buff);
  }
*/
  DrawXYZAxes();
  Send(Msg(), PIMsg_Active);
  PIDrwTools::SetCurrentBaseWdg(this);
}

/* --Methode-- */
void PIDraw3DWdg::Ptr3Move(int x, int y)
{
  DrawXYZAxes();
  double rapx = (double)(lPx-x)/XSize();
  if (rapx > 0.) rapx = rapx*2.+1;
  else rapx += 1.;
  if (rapx < 0.3)  rapx = 0.3;
  if (rapx > 3.)  rapx = 3.;
  double rapy = (double)(y-lPy)/YSize();
  if (rapy > 0.) rapy = rapy*2.+1;
  else rapy += 1.;
  if (rapy < 0.3)  rapy = 0.3;
  if (rapy > 3.)  rapy = 3.;
/*
  {
  char buff[256];
  sprintf(buff, "Ptr3Move() Rap=%g %g -> %g %g %g     ", rapx, rapy, rapy*clCO, rapx*cDax, rapx*cDay);
  mWGrC->DrawOpaqueString(0,20,buff);
  }
*/
  mGr3d->ZoomInOut(rapy*clCO, rapx*cDax, rapx*cDay, false);
  DrawXYZAxes();
}

/* --Methode-- */
void PIDraw3DWdg::But3Release(int x, int y)
{
  DrawXYZAxes();
  SelPointerShape(PI_ArrowPointer);
  mWGrC->SelForeground(lCol);
  SetDrawers3DView();
  Refresh();
}


/* --Methode-- */
void PIDraw3DWdg::DrawXYZAxes()
{
  mWGrC->SelGOMode(PI_GOXOR);
  PIGrCoord x1,y1,z1,x2,y2,z2;
  x1 = cXc;  y1 = cYc;  z1 = cZc;
  x2 = cXc+cUlen;   y2 = cYc;   z2 = cZc; 
  mGr3d->DrawLine3D(x1, y1, z1, x2, y2, z2);
  x2 = cXc+cUlen*1.1;
  mGr3d->DrawString3D(x2, y2, z2, "X");
  x2 = cXc;   y2 = cYc+cUlen;   z2 = cZc; 
  mGr3d->DrawLine3D(x1, y1, z1, x2, y2, z2);
  y2 = cYc+cUlen*1.1;
  mGr3d->DrawString3D(x2, y2, z2, "Y");   
  x2 = cXc;   y2 = cYc;   z2 = cZc+cUlen; 
  mGr3d->DrawLine3D(x1, y1, z1, x2, y2, z2);
  z2 = cZc+cUlen*1.1;
  mGr3d->DrawString3D(x2, y2, z2, "Z");   
//   mGr3d->DrawCircle(0., 0., daxO*0.30);
  char buff[256];
  double xc,yc,zc,xo,yo,zo,teta,phi,psi,dax,day,co,dco;
  mGr3d->Get3DCS(xc,yc,zc,xo,yo,zo,teta,phi,psi,dax,day,co,dco);
  sprintf(buff, " C: %g %g %g -> O: %g %g %g  (T/P0= %g %g)     ", xc,yc,zc, xo, yo, zo, cTeta, cPhi);
  mWGrC->DrawString(0,20,buff);
  sprintf(buff, " T,P= %g %g %g lCO= %g  dax= %g %g UL=%g    ", teta,phi,psi,co,dax,day,cUlen); 
  mWGrC->DrawString(0,40,buff);
  mWGrC->SelGOMode(PI_GOCopy);  

}


/* --Methode-- */
void PIDraw3DWdg::But1Press(int x, int y)
{
  Send(Msg(), PIMsg_Active);
  PIDrwTools::SetCurrentBaseWdg(this);
  mPx = x;  mPy = y;
  if ( (x > 50) || ( y > 50) ) return; 
  Update3DView();
}

/*   Pour debugger sur bouton-3 
static int isw = 0;
void PIDraw3DWdg::But3Press(int x, int y)
x -= XSize()/2;
y -= YSize()/2;

double fx = (double)x/XSize(); 
double fy = (double)y/YSize(); 
if ( (fx<0.2) && (fx>-0.2) && (fy<0.2) && (fy>-0.2) ) {
  
  if ((isw%3) == 0) { 
    Set3DView(0., 0., 0., 0., 0., -3. , 0.3, 0.3, 2); 
    puts("\n Set3DView(0., 0., 0., 0., 0., -3. , 0.3, 0.3, 2)");
  }
  else if ((isw%3) == 1) { 
    Set3DView(0., 0., 0., 2., 1., 3. , 0.3, 0.3, 2);
    puts("\n Set3DView(0., 0., 0., 2., 1., 3. , 0.3, 0.3, 2)");
  }
  else if ((isw%3) == 2) { 
    Set3DView_Obs(0.,4.,0.,3.14159/2.,-3.14159/2.,0.,0.25,0.25,4.,2.);
    puts("\n Set3DView_Obs(0.,4.,0.,3.14159/2.,3.14159/2.,0.,0.25,0.25,4.,2.)");
  }
  isw++;
  mGr3d->PrintCS();
  double xc,yc,zc,xo,yo,zo,teta,phi,psi,dax,day,co,dco;
  mGr3d->Get3DCS(xc,yc,zc,xo,yo,zo,teta,phi,psi,dax,day,co,dco);
  mGr3d->Set3DCS(xc,yc,zc,xo,yo,zo,dax,day,dco,psi);
  mGr3d->PrintCS();
  mGr3d->Set3DCS_Obs(xo,yo,zo,teta,phi,psi,dax,day,co,dco);
  mGr3d->PrintCS();
  puts(" --------------------- \n");
  Refresh();
  return;
}
if ((x > 0) && (y > 0) )  { 
  puts(" But3Press()Set3DView(0., 0., 0., 5., 0., 0. , 0.3, 0.3, 2)");
  Set3DView(0., 0., 0., 5., 0., 0. , 0.3, 0.3, 2);
}
else if ((x < 0) && (y > 0) )  { 
  puts(" But3Press()Set3DView(0., 0., 0., 0., 5., 1. , 0.3, 0.3, 2) ");
  Set3DView(0., 0., 0., 0., 5., 1. , 0.3, 0.3, 2);
}
else  if ((x < 0) && (y < 0) ) {
  puts(" But3Press()Set3DView(0., 0., 0., 1., 1., 5. , 0.3, 0.3, 2)");
  Set3DView(0., 0., 0., 1., 1., 5. , 0.3, 0.3, 2);
}
else {
  puts(" But3Press()Set3DView(0., 0., 0., -3., -3., 3. , 0.3, 0.3, 2)");
  Set3DView(0., 0., 0., -3., -3., 3. , 0.3, 0.3, 2);
}

Refresh();
*/
