// File:	ViewerTest_ObjectsCommands.cxx
// Created:	Thu Nov 12 15:50:42 1998
// Author:	Robert COUBLANC
//		<rob@robox.paris1.matra-dtv.fr>


//===============================================
//
//    AIS Objects Creation : Datums (axis,trihedrons,lines,planes)
//
//===============================================

#ifdef HAVE_CONFIG_H
# include <config.h>
#endif

#include <ViewerTest.hxx>

#include <string.h>

#include <Quantity_NameOfColor.hxx>
#include <Draw_Interpretor.hxx>
#include <Draw.hxx>
#include <Draw_Appli.hxx>
#include <DBRep.hxx>


#include <TCollection_AsciiString.hxx>
#include <V3d_Viewer.hxx>
#include <V3d_View.hxx>
#include <V3d.hxx>

#include <AIS_Shape.hxx>
#include <AIS_DisplayMode.hxx>
#include <TColStd_MapOfInteger.hxx>
#include <AIS_MapOfInteractive.hxx>
#include <ViewerTest_DoubleMapOfInteractiveAndName.hxx>
#include <ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName.hxx>
#include <ViewerTest_EventManager.hxx>

#include <TopoDS_Solid.hxx>
#include <BRepTools.hxx>
#include <BRep_Builder.hxx>
#include <TopAbs_ShapeEnum.hxx>

#include <TopoDS.hxx>
#include <BRep_Tool.hxx>
#include <TopExp_Explorer.hxx>

#include <BRepAdaptor_Curve.hxx>
#include <BRepAdaptor_Surface.hxx>

#include <TopAbs.hxx>
#include <TopExp.hxx>
#include <TopoDS_Vertex.hxx>
#include <TopoDS_Shape.hxx>
#include <TopoDS_Face.hxx>

#include <Draw_Window.hxx>
#include <AIS_ListIteratorOfListOfInteractive.hxx>
#include <AIS_ListOfInteractive.hxx>
#include <AIS_DisplayMode.hxx>
#include <AIS_Shape.hxx>

#include <AIS_InteractiveContext.hxx>
#include <Geom_Plane.hxx>
#include <gp_Pln.hxx>
#include <AIS_AngleDimension.hxx>
#include <TCollection_ExtendedString.hxx>
#include <GC_MakePlane.hxx>
#include <gp_Circ.hxx>
#include <AIS_Axis.hxx>
#include <Geom_Axis2Placement.hxx>
#include <Geom_Axis1Placement.hxx>
#include <AIS_Trihedron.hxx>
#include <AIS_Axis.hxx>
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif

extern ViewerTest_DoubleMapOfInteractiveAndName& GetMapOfAIS();
Standard_IMPORT int ViewerMainLoop(Standard_Integer argc, char** argv);
extern Handle(AIS_InteractiveContext)& TheAISContext();


//==============================================================================
//function : Vtrihedron 2d
//purpose  : Create a plane with a 2D  trihedron from a faceselection
//Draw arg : vtri2d  name  
//==============================================================================
#include <AIS_PlaneTrihedron.hxx>



static int VTrihedron2D (Draw_Interpretor& di, Standard_Integer argc, char** argv)
     
{
  // Verification des arguments
  if ( argc!=2) {di<<argv[0]<<" error"<<"\n"; return 1;}
  
  // Declarations
  Standard_Integer myCurrentIndex;
  // Fermeture des contextes 
  TheAISContext()->CloseAllContexts();
  // Ouverture d'un contexte local et recuperation de son index.
  TheAISContext()->OpenLocalContext();
  myCurrentIndex=TheAISContext()->IndexOfCurrentLocal();
  // On active les modes de selections faces.
  TheAISContext()->ActivateStandardMode (AIS_Shape::SelectionType(4) );
  di<<" Select a face ."<<"\n";
  
  // Boucle d'attente waitpick.
  Standard_Integer argccc = 5;
  char *bufff[] = { "VPick", "X", "VPickY","VPickZ", "VPickShape" };
  char **argvvv = bufff;
  while (ViewerMainLoop( argccc, argvvv) ) { }
  // fin de la boucle
  
  TopoDS_Shape ShapeB;
  for(TheAISContext()->InitSelected() ;TheAISContext()->MoreSelected() ;TheAISContext()->NextSelected() ) {
    ShapeB = TheAISContext()->SelectedShape();
  }
  
  TopoDS_Face  FaceB=TopoDS::Face(ShapeB);
  
  // Construction du Plane
  // recuperation des edges des faces.
  TopExp_Explorer FaceExpB(FaceB,TopAbs_EDGE);
  
  TopoDS_Edge EdgeB=TopoDS::Edge(FaceExpB.Current() );
  // declarations 
  gp_Pnt A,B,C;
  
  // si il y a plusieurs edges
  if (FaceExpB.More() ) {
    FaceExpB.Next();
    TopoDS_Edge EdgeC=TopoDS::Edge(FaceExpB.Current() );
    BRepAdaptor_Curve theCurveB(EdgeB);
    BRepAdaptor_Curve theCurveC(EdgeC);
    A=theCurveC.Value(0.1);
    B=theCurveC.Value(0.9);
    C=theCurveB.Value(0.5);
  }
  else {
    // FaceB a 1 unique edge courbe
    BRepAdaptor_Curve theCurveB(EdgeB);
    A=theCurveB.Value(0.1);
    B=theCurveB.Value(0.9);
    C=theCurveB.Value(0.5);
  }
  // Construction du Geom_Plane
  GC_MakePlane MkPlane(A,B,C);
  Handle(Geom_Plane) theGeomPlane=MkPlane.Value();
  
  // Construction de l'AIS_PlaneTrihedron
  Handle(AIS_PlaneTrihedron) theAISPlaneTri= new AIS_PlaneTrihedron(theGeomPlane );
  
  // Fermeture du contexte local.
  TheAISContext()->CloseLocalContext(myCurrentIndex);
  
  // on le display & bind
  TheAISContext()->Display(theAISPlaneTri );
  GetMapOfAIS().Bind ( theAISPlaneTri ,argv[1]);
  
  return 0; 
}



//==============================================================================
//function : VTriherdron
//author   : ege
//purpose  : Create a trihedron. If no arguments are set, the default
//           trihedron (Oxyz) is created.
//Draw arg : vtrihedron  name  [Xo] [Yo] [Zo] [Zu] [Zv] [Zw] [Xu] [Xv] [Xw]
//==============================================================================

static int VTrihedron (Draw_Interpretor& di, Standard_Integer argc, char** argv)
     
{
  // Verification des arguments
  if ( argc<2 || argc>11) {di<<argv[0]<<" Syntaxe error"<<"\n"; return 1;}
  
  // Declarations et creation des objets par default
  TCollection_AsciiString     name=argv[1];

  if(argc > 5 && argc!=11)
    {di<<argv[0]<<" Syntaxe error"<<"\n"; return 1;}

  // Cas ou il y a des arguments
  Standard_Real coord[9]={0.,0.,0.,0.,0.,1.,1.,0.,0.};
  if (argc>2){
    Standard_Integer i ;
    for( i=0;i<=2;i++)
      coord[i]= atof(argv[2+i]);
    
    if(argc>5){
      for(i=0;i<=2;i++){
	coord[3+i] = atof(argv[6+i]);
	coord[6+i] = atof(argv[8+i]);
      }
    }
  }
  gp_Pnt ThePoint(coord[0],coord[1],coord[2]);
  gp_Dir TheZVector(coord[3],coord[4],coord[5]);
  gp_Dir TheXVector(coord[6],coord[7],coord[8]);
  
  if ( !TheZVector.IsNormal(TheXVector,PI/180)) {di<<argv[0]<<" VectorX is not normal to VectorZ"<<"\n"; return 1;}
  
  Handle(Geom_Axis2Placement) OrigineAndAxii=new Geom_Axis2Placement(ThePoint,TheZVector,TheXVector);
  
  // Creation du triedre
  Handle(AIS_Trihedron) aShape= new AIS_Trihedron(OrigineAndAxii);
  GetMapOfAIS().Bind(aShape,name);
  TheAISContext()->Display(aShape);
  
  return 0; 
}




//==============================================================================
//function : VSize
//author   : ege
//purpose  : Change the size of a named or selected trihedron
//           if no name : it affects the trihedrons witch are selected otherwise nothing is donne
//           if no value, the value is set at 100 by default
//Draw arg : vsize [name] [size]
//==============================================================================

static int VSize (Draw_Interpretor& di, Standard_Integer argc, char** argv)
     
{
  // Declaration de booleens
  Standard_Boolean             ThereIsName;
  Standard_Boolean             ThereIsCurrent;
//  Standard_Boolean             IsTrihedron;
  Standard_Real                value;
  Standard_Boolean             hascol; 
#ifdef DEB
  Quantity_NameOfColor         col;
#else
  Quantity_NameOfColor         col = Quantity_NOC_BLACK ;
#endif
  
  // Verification des arguments
  if ( argc>3 ) {di<<argv[0]<<" Syntaxe error"<<"\n"; return 1;}
  
  // Verification du nombre d'arguments
  if (argc==1)      {ThereIsName=Standard_False;value=100;}
  else if (argc==2) {ThereIsName=Standard_False;value=atof(argv[1]);}
  else              {ThereIsName=Standard_True;value=atof(argv[2]);}

  // On ferme le contexte local pour travailler dans le contexte global
  if(TheAISContext()->HasOpenedContext()) 
    TheAISContext()->CloseLocalContext();
  
  // On set le booleen ThereIsCurrent
  if (TheAISContext() -> NbCurrents() > 0) {ThereIsCurrent=Standard_True;}
  else {ThereIsCurrent=Standard_False;}
  
  
  
  //===============================================================
  // Il n'y a pas de nom  mais des objets selectionnes
  //===============================================================
  if (!ThereIsName && ThereIsCurrent) {
    
    ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName it (GetMapOfAIS());
    
    while ( it.More() ) {
      
      Handle(AIS_InteractiveObject) aShape= it.Key1();
      
      if (  TheAISContext()->IsCurrent(aShape) )      {
	
	// On verifie que l'AIS InteraciveObject selectionne est bien 
	// un AIS_Trihedron
	if (aShape->Type()==AIS_KOI_Datum && aShape->Signature()==3) {
	  
	  if (aShape->HasColor()) {
	    hascol=Standard_True;
	    
	    // On recupere la couleur de aShape
	    col=aShape->Color();}
	  
	  else hascol=Standard_False;
	  
	  // On downcast aShape  de AIS_InteractiveObject a AIS_Trihedron
	  // pour lui appliquer la methode SetSize()
	  Handle(AIS_Trihedron) aTrihedron = *(Handle(AIS_Trihedron)*) &aShape;
	  
	  // C'est bien un triedre,on chage sa valeur!
	  aTrihedron->SetSize(value);
	  
	  // On donne la couleur au Trihedron
	  if(hascol)   aTrihedron->SetColor(col);
	  else         aTrihedron->UnsetColor();
	  
	  
	  // The trihedron hasn't be errased from the map
	  // so you just have to redisplay it
	  TheAISContext() ->Redisplay(aTrihedron,Standard_False);
	  
	}
	
      }
      
      it.Next();
      
      
      
    }
    
    TheAISContext() ->UpdateCurrentViewer();
  }
  
  //===============================================================
  // Il n'y a pas d'arguments et aucuns objets selectionne Rien A Faire!
  //===============================================================
  
  
      
  //===============================================================
  // Il y a un nom de triedre passe en argument
  //===============================================================
  if (ThereIsName) {
    TCollection_AsciiString name=argv[1];
    
    // on verifie que ce nom correspond bien a une shape
    Standard_Boolean IsBound= GetMapOfAIS().IsBound2(name);
    
    if (IsBound) {
      
      // on recupere la shape dans la map des objets displayes
      Handle(AIS_InteractiveObject) aShape = GetMapOfAIS().Find2(name);
      
      // On verifie que l'AIS InteraciveObject est bien 
      // un AIS_Trihedron
      if (aShape->Type()==AIS_KOI_Datum && aShape->Signature()==3) {
	
	if (aShape->HasColor()) {
	  hascol=Standard_True;
	  
	  // On recupere la couleur de aShape
	  col=aShape->Color();}
	
	else hascol=Standard_False;
	
	// On downcast aShape de AIS_InteractiveObject a AIS_Trihedron
	// pour lui appliquer la methode SetSize()
	Handle(AIS_Trihedron) aTrihedron = *(Handle(AIS_Trihedron)*) &aShape;
	
	// C'est bien un triedre,on chage sa valeur
	aTrihedron->SetSize(value);
	
	// On donne la couleur au Trihedron
	if(hascol)   aTrihedron->SetColor(col);
	else         aTrihedron->UnsetColor();
	
	// The trihedron hasn't be errased from the map
	// so you just have to redisplay it
	TheAISContext() ->Redisplay(aTrihedron,Standard_False);
      
	TheAISContext() ->UpdateCurrentViewer();
      }
    }
  }
return 0; 
}


//==============================================================================

//==============================================================================
//function : VPlaneTrihedron
//purpose  : Create a plane from a trihedron selection. If no arguments are set, the default
//Draw arg : vplanetri  name  
//==============================================================================
#include <AIS_Plane.hxx>



static int VPlaneTrihedron (Draw_Interpretor& di, Standard_Integer argc, char** argv)
     
{
  // Verification des arguments
  if ( argc!=2) {di<<argv[0]<<" error"<<"\n"; return 1;}
  
  // Declarations
  Standard_Integer myCurrentIndex;
 // Fermeture des contextes locaux
  TheAISContext()->CloseAllContexts();
  
  // On recupere tous les trihedrons de la GetMapOfAIS() 
  // et on active le mode de selection par face.
  // =================================================
  
  // Ouverture d'un contexte local et recuperation de son index.
  TheAISContext()->OpenLocalContext(Standard_False);
  myCurrentIndex=TheAISContext()->IndexOfCurrentLocal();
  
  ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName it (GetMapOfAIS());
  while(it.More()){
    Handle(AIS_InteractiveObject) ShapeA=it.Key1();
    // On verifie que c'est bien un trihedron
    if (ShapeA->Type()==AIS_KOI_Datum  && ShapeA->Signature()==3  ) {
      // on le downcast
      Handle(AIS_Trihedron) TrihedronA =((*(Handle(AIS_Trihedron)*)&ShapeA));
      // on le charge dans le contexte et on active le mode Plane.
      TheAISContext()->Load(TrihedronA,0,Standard_False);
      TheAISContext()->Activate(TrihedronA,3);
    }
    it.Next();
  }
  
  di<<" Select a plane."<<"\n";
  // Boucle d'attente waitpick.
  Standard_Integer argccc = 5;
  char *bufff[] = { "VPick", "X", "VPickY","VPickZ", "VPickShape" };
  char **argvvv = bufff;
  while (ViewerMainLoop( argccc, argvvv) ) { }
  // fin de la boucle
  
  Handle(AIS_InteractiveObject) theIOB;
  for(TheAISContext()->InitSelected() ;TheAISContext()->MoreSelected() ;TheAISContext()->NextSelected() ) {
    theIOB = TheAISContext()->Interactive();
  }
  // on le downcast
  Handle(AIS_Plane) PlaneB =((*(Handle(AIS_Plane)*)&theIOB));
  
  // Fermeture du contexte local.
  TheAISContext()->CloseLocalContext(myCurrentIndex);
  
  // Construction de l'AIS_Plane
  //gp_Pnt A,B,C;
  //Handle(Geom_Plane) theGeomPlane;
  //PlaneB->PlaneAttributes(theGeomPlane,A,B,C);
  //Handle(AIS_PlaneTrihedron) theAISPlaneTri= new AIS_PlaneTrihedron(theGeomPlane );
  
  // on le display & bind
  TheAISContext()->Display(PlaneB );
  GetMapOfAIS().Bind ( PlaneB ,argv[1]);
  
  return 0; 
}



//==============================================================================
// Fonction        First click      2de click
// 
// vaxis           vertex           vertex
//                 edge             None
// vaxispara       edge             vertex
// vaxisortho      edge             Vertex
// vaxisinter      Face             Face
//==============================================================================

//==============================================================================
//function : VAxisBuilder
//purpose  : 
//Draw arg : vaxis AxisName Xa Ya Za Xb Yb Zb
//==============================================================================
#include <TopoDS_Edge.hxx>
#include <TopoDS_Vertex.hxx>
#include <TopExp.hxx>
#include <Geom_Line.hxx>

static int VAxisBuilder(Draw_Interpretor& di, Standard_Integer argc, char** argv) 
{
  // Declarations
  Standard_Boolean HasArg;
  TCollection_AsciiString name;
  Standard_Integer MyCurrentIndex;
  
  // Verification
  if (argc<2 || argc>8 ) {di<<" Syntaxe error"<<"\n";return 1;}
  if (argc==8) HasArg=Standard_True;
  else HasArg=Standard_False;
  
  name=argv[1];
  // Fermeture des contextes
  TheAISContext()->CloseAllContexts();
  
  // Cas ou il y a des arguments
  // Purpose: Teste le constructeur AIS_Axis::AIS_Axis(x: Line from Geom)
  if (HasArg) {
    Standard_Real coord[6];
    for(Standard_Integer i=0;i<=5;i++){
      coord[i]=atof(argv[2+i]);
    }
    gp_Pnt p1(coord[0],coord[1],coord[2]), p2(coord[3],coord[4],coord[5]) ;
    
    gp_Vec myVect (p1,p2);
    Handle(Geom_Line) myLine=new Geom_Line (p1 ,myVect );
    Handle(AIS_Axis) TheAxis=new AIS_Axis (myLine );
    GetMapOfAIS().Bind (TheAxis,name);
    TheAISContext()->Display(TheAxis);
  }
  
  // Pas d'arguments
  else {
    // fonction vaxis
    // Purpose: Teste le constructeur AIS_Axis::AIS_Axis (x:Axis1Placement from Geom)
    if ( !strcasecmp(argv[0], "vaxis")) {
      TheAISContext()->OpenLocalContext();
      MyCurrentIndex=TheAISContext()->IndexOfCurrentLocal();
      
      // Active le mode edge et le mode vertex
      TheAISContext()->ActivateStandardMode(AIS_Shape::SelectionType(1) );
      TheAISContext()->ActivateStandardMode(AIS_Shape::SelectionType(2) );
      di<<" Select an edge or a vertex."<<"\n";
      
      // Boucle d'attente waitpick.
      Standard_Integer argcc = 5;
      char *buff[] = { "VPick", "X", "VPickY","VPickZ", "VPickShape" };
      char **argvv = buff;
      while (ViewerMainLoop( argcc, argvv) ) { }
      // fin de la boucle 
      
      // recuperation de la shape.
      TopoDS_Shape ShapeA;
      for(TheAISContext()->InitSelected() ;TheAISContext()->MoreSelected() ;TheAISContext()->NextSelected() ) {
	ShapeA = TheAISContext()->SelectedShape();
      }
      // recuperation de l'AIS_InteractiveObject
      //Handle(AIS_InteractiveObject) myAISio=TheAISContext()->Current();
      // down cast en AIS_Point si sig et type
      // AIS_Point -> Geom_Pnt ....
      
      if (ShapeA.ShapeType()==TopAbs_VERTEX) {
	// on desactive le mode edge
	TheAISContext()->DeactivateStandardMode(AIS_Shape::SelectionType(2) );
	di<<" Select a different vertex."<<"\n";
	
	TopoDS_Shape ShapeB;
	do {
	  // Boucle d'attente waitpick.
	  Standard_Integer argccc = 5;
	  char *bufff[] = { "VPick", "X", "VPickY","VPickZ", "VPickShape" };
	  char **argvvv = bufff;
	  while (ViewerMainLoop( argccc, argvvv) ) { }
	  // fin de la boucle 
	  for(TheAISContext()->InitSelected() ;TheAISContext()->MoreSelected() ;TheAISContext()->NextSelected() ) {
	    ShapeB = TheAISContext()->SelectedShape();
	  }
	  
	  
	} while(ShapeB.IsSame(ShapeA) );
	
	// Fermeture du context local
	TheAISContext()->CloseLocalContext(MyCurrentIndex);
	
	// Construction de l'axe 
	gp_Pnt   A=BRep_Tool::Pnt(TopoDS::Vertex(ShapeA)  );
	gp_Pnt   B=BRep_Tool::Pnt(TopoDS::Vertex(ShapeB)  );
	gp_Vec   V (A,B);
	gp_Dir   D (V);
	Handle(Geom_Axis1Placement) OrigineAndVect=new Geom_Axis1Placement (A,D);
	Handle(AIS_Axis) TheAxis=new AIS_Axis (OrigineAndVect);
	GetMapOfAIS().Bind (TheAxis,name);
	TheAISContext()->Display(TheAxis);
      } 
      else {
	// Un unique edge (ShapeA) a ete picke
	// Fermeture du context local
	TheAISContext()->CloseLocalContext(MyCurrentIndex);
	// Constuction de l'axe 
	TopoDS_Edge    ed =TopoDS::Edge(ShapeA);
	TopoDS_Vertex  Va,Vb;
	TopExp::Vertices(ed,Va,Vb );
	gp_Pnt A=BRep_Tool::Pnt(Va);
	gp_Pnt B=BRep_Tool::Pnt(Vb);
	gp_Vec  V (A,B);
	gp_Dir   D (V);
	Handle(Geom_Axis1Placement) OrigineAndVect=new Geom_Axis1Placement (A,D);
	Handle(AIS_Axis) TheAxis=new AIS_Axis (OrigineAndVect);
	GetMapOfAIS().Bind (TheAxis,name);
	TheAISContext()->Display(TheAxis);
      }
      
    }
    
    // Fonction axispara
    // Purpose: Teste le constructeur AIS_Axis::AIS_Axis(x: Axis2Placement from Geom, y: TypeOfAxis from AIS)
    else if ( !strcasecmp(argv[0], "vaxispara")) {
      
      TheAISContext()->OpenLocalContext();
      MyCurrentIndex=TheAISContext()->IndexOfCurrentLocal();
      
      // Active le mode edge 
      TheAISContext()->ActivateStandardMode(AIS_Shape::SelectionType(2) );
      di<<" Select an edge."<<"\n";
      
      // Boucle d'attente waitpick.
      Standard_Integer argcc = 5;
      char *buff[] = { "VPick", "X", "VPickY","VPickZ", "VPickShape" };
      char **argvv = buff;
      while (ViewerMainLoop( argcc, argvv) ) { }
      // fin de la boucle 
      
      TopoDS_Shape ShapeA;
      for(TheAISContext()->InitSelected() ;TheAISContext()->MoreSelected() ;TheAISContext()->NextSelected() ) {
	ShapeA = TheAISContext()->SelectedShape();
      }
      // Active le mode vertex et deactive edges
      TheAISContext()->DeactivateStandardMode(AIS_Shape::SelectionType(2) );
      TheAISContext()->ActivateStandardMode(AIS_Shape::SelectionType(1) );
      di<<" Select a vertex."<<"\n";
      
      // Boucle d'attente waitpick.
      Standard_Integer argccc = 5;
      char *bufff[] = { "VPick", "X", "VPickY","VPickZ", "VPickShape" };
      char **argvvv = bufff;
      while (ViewerMainLoop( argccc, argvvv) ) { }
      // fin de la boucle 
      
      // On peut choisir un pnt sur l'edge
      TopoDS_Shape ShapeB;
      for(TheAISContext()->InitSelected() ;TheAISContext()->MoreSelected() ;TheAISContext()->NextSelected() ) {
	ShapeB = TheAISContext()->SelectedShape();
      }
      // Fermeture du context local
      TheAISContext()->CloseLocalContext(MyCurrentIndex);
      
      // Construction de l'axe
      TopoDS_Edge    ed=TopoDS::Edge(ShapeA) ;
      gp_Pnt B=BRep_Tool::Pnt(TopoDS::Vertex(ShapeB) );
      TopoDS_Vertex  Va,Vc;
      TopExp::Vertices(ed,Va,Vc );
      gp_Pnt A=BRep_Tool::Pnt(Va);
      gp_Pnt C=BRep_Tool::Pnt(Vc);
      gp_Vec  V (A,C);
      gp_Dir   D (V);
      Handle(Geom_Axis1Placement) OrigineAndVect=new Geom_Axis1Placement (B,D);
      Handle(AIS_Axis) TheAxis=new AIS_Axis (OrigineAndVect);
      GetMapOfAIS().Bind (TheAxis,name);
      TheAISContext()->Display(TheAxis);
      
    }
    
    // Fonction axisortho
    else  {
      TheAISContext()->OpenLocalContext();
      MyCurrentIndex=TheAISContext()->IndexOfCurrentLocal();
      
      // Active le mode edge 
      TheAISContext()->ActivateStandardMode(AIS_Shape::SelectionType(2) );
      di<<" Select an edge."<<"\n";
      
      // Boucle d'attente waitpick.
      Standard_Integer argcc = 5;
      char *buff[] = { "VPick", "X", "VPickY","VPickZ", "VPickShape" };
      char **argvv = buff;
      while (ViewerMainLoop( argcc, argvv) ) { }
      // fin de la boucle 
      
      TopoDS_Shape ShapeA;
      for(TheAISContext()->InitSelected() ;TheAISContext()->MoreSelected() ;TheAISContext()->NextSelected() ) {
	ShapeA = TheAISContext()->SelectedShape();
      }
      // Active le mode vertex et deactive edges
      TheAISContext()->DeactivateStandardMode(AIS_Shape::SelectionType(2) );
      TheAISContext()->ActivateStandardMode(AIS_Shape::SelectionType(1) );
      di<<" Slect a vertex."<<"\n";
      
      // Boucle d'attente waitpick.
      Standard_Integer argccc = 5;
      char *bufff[] = { "VPick", "X", "VPickY","VPickZ", "VPickShape" };
      char **argvvv = bufff;
      while (ViewerMainLoop( argccc, argvvv) ) { }
      // fin de la boucle 
      
      // On peut choisir un pnt sur l'edge
      TopoDS_Shape ShapeB;
      for(TheAISContext()->InitSelected() ;TheAISContext()->MoreSelected() ;TheAISContext()->NextSelected() ) {
	ShapeB = TheAISContext()->SelectedShape();
      }
      // Fermeture du context local
      TheAISContext()->CloseLocalContext(MyCurrentIndex);
      
      // Construction de l'axe
      TopoDS_Edge    ed=TopoDS::Edge(ShapeA) ;
      gp_Pnt B=BRep_Tool::Pnt(TopoDS::Vertex(ShapeB) );
      TopoDS_Vertex  Va,Vc;
      TopExp::Vertices(ed,Va,Vc );
      gp_Pnt A=BRep_Tool::Pnt(Va);
      gp_Pnt C=BRep_Tool::Pnt(Vc);
      gp_Pnt E(A.Y()+A.Z()-C.Y()-C.Z()  ,C.X()-A.X() ,C.X()-A.X() );
      // W=AE est un vecteur orthogonal a AC
      gp_Vec  V (A,E);
      gp_Dir   D (V);
      Handle(Geom_Axis1Placement) OrigineAndVect=new Geom_Axis1Placement (B,D);
      Handle(AIS_Axis) TheAxis=new AIS_Axis (OrigineAndVect);
      GetMapOfAIS().Bind (TheAxis,name);
      TheAISContext()->Display(TheAxis);
      
    }
    
  }
  return 0;
}


//==============================================================================
// Fonction        First click      Result
// 
// vpoint          vertex           AIS_Point=Vertex
//                 edge             AIS_Point=Middle of the edge
//==============================================================================

//==============================================================================
//function : VPointBuilder
//purpose  : Build an AIS_Point from coordinates or with a selected vertex or edge
//Draw arg : vpoint PoinName [Xa] [Ya] [Za]
//==============================================================================
#include <TopoDS_Edge.hxx>
#include <TopoDS_Vertex.hxx>
#include <TopExp.hxx>
#include <AIS_Point.hxx>
#include <Geom_CartesianPoint.hxx>

static int VPointBuilder(Draw_Interpretor& di, Standard_Integer argc, char** argv) 
{
  // Declarations
  Standard_Boolean HasArg;
  TCollection_AsciiString name;
  Standard_Integer myCurrentIndex;
  
  // Verification
  if (argc<2 || argc>5 ) {di<<" Syntaxe error"<<"\n";return 1;}
  if (argc==5) HasArg=Standard_True;
  else HasArg=Standard_False;
  
  name=argv[1];
  // Fermeture des contextes
  TheAISContext()->CloseAllContexts();
  
  // Il y a des arguments: teste l'unique constructeur AIS_Pnt::AIS_Pnt(Point from Geom)
  if (HasArg) {
    Standard_Real thecoord[3];
    for(Standard_Integer i=0;i<=2;i++)
      thecoord[i]=atof(argv[2+i]);
    Handle(Geom_CartesianPoint )  myGeomPoint= new Geom_CartesianPoint (thecoord[0],thecoord[1],thecoord[2]);
    Handle(AIS_Point)  myAISPoint=new AIS_Point(myGeomPoint );
    GetMapOfAIS().Bind (myAISPoint,name);
    TheAISContext()->Display(myAISPoint);
  }
  
  // Il n'a pas d'arguments
  else {
    TheAISContext()->OpenLocalContext();
    myCurrentIndex=TheAISContext()->IndexOfCurrentLocal();
    
    // Active le mode Vertex et Edges
    TheAISContext()->ActivateStandardMode (AIS_Shape::SelectionType(1) );
    TheAISContext()->ActivateStandardMode (AIS_Shape::SelectionType(2) );
    di<<" Select a vertex or an edge(build the middle)"<<"\n";
    
    // Boucle d'attente waitpick.
    Standard_Integer argcc = 5;
    char *buff[] = { "VPick", "X", "VPickY","VPickZ", "VPickShape" };
    char **argvv = buff;
    while (ViewerMainLoop( argcc, argvv) ) { }
    // fin de la boucle
    
    TopoDS_Shape ShapeA;
    for (TheAISContext()->InitSelected() ;TheAISContext()->MoreSelected() ;TheAISContext()->NextSelected() ) {
      ShapeA= TheAISContext()->SelectedShape();
    }
    
    if (ShapeA.ShapeType()==TopAbs_VERTEX ) {
      // Un vertex a ete selectionne
      // Fermeture du context local
      TheAISContext()->CloseLocalContext(myCurrentIndex);
      
      // Construction du point
      gp_Pnt A=BRep_Tool::Pnt(TopoDS::Vertex(ShapeA ) );
      Handle(Geom_CartesianPoint) myGeomPoint= new Geom_CartesianPoint (A );
      Handle(AIS_Point)  myAISPoint = new AIS_Point  (myGeomPoint );
      GetMapOfAIS().Bind(myAISPoint,name);
      TheAISContext()->Display(myAISPoint);
    }
    else {
      // Un Edge a ete selectionne
      // Fermeture du context local
      TheAISContext()->CloseLocalContext(myCurrentIndex);
      
      // Construction du point milieu de l'edge
      TopoDS_Edge myEdge=TopoDS::Edge(ShapeA);
      TopoDS_Vertex myVertexA,myVertexB;
      TopExp::Vertices (myEdge ,myVertexA ,myVertexB );
      gp_Pnt A=BRep_Tool::Pnt(myVertexA );
      gp_Pnt B=BRep_Tool::Pnt(myVertexB );
      // M est le milieu de [AB]
      Handle(Geom_CartesianPoint) myGeomPointM= new Geom_CartesianPoint ( (A.X()+B.X())/2  , (A.Y()+B.Y())/2  , (A.Z()+B.Z())/2  );
      Handle(AIS_Point)  myAISPointM = new AIS_Point  (myGeomPointM );
      GetMapOfAIS().Bind(myAISPointM,name);
      TheAISContext()->Display(myAISPointM);
    }
    
  }
  return 0;
  
}

//==============================================================================
// Fonction        1st click   2de click  3de click   
// vplane          Vertex      Vertex     Vertex
//                 Vertex      Edge
//                 Edge        Vertex
//                 Face
// vplanepara      Face        Vertex
//                 Vertex      Face
// vplaneortho     Face        Edge
//                 Edge        Face
//==============================================================================

//==============================================================================
//function : VPlaneBuilder
//purpose  : Build an AIS_Plane from selected entities or Named AIs components
//Draw arg : vplane PlaneName [AxisName]  [PointName]
//                            [PointName] [PointName] [PointName]
//                            [PlaneName] [PointName]
//==============================================================================

#include <TopoDS_Edge.hxx>
#include <TopoDS_Vertex.hxx>
#include <TopoDS_Face.hxx>
#include <TopExp.hxx>
#include <AIS_Plane.hxx>
#include <Geom_CartesianPoint.hxx>
#include <Geom_Plane.hxx>
#include <BRepExtrema_ExtPC.hxx>
#include <BRepExtrema_ExtPF.hxx>
#include <BRepAdaptor_Surface.hxx>
#include <gp_Pln.hxx>
#include <GC_MakePlane.hxx>

static int VPlaneBuilder(Draw_Interpretor& di, Standard_Integer argc, char** argv) 
{
  // Declarations
  Standard_Boolean HasArg;
  TCollection_AsciiString name;
  Standard_Integer myCurrentIndex;
  
  // Verification
  if (argc<2 || argc>5 ) {di<<" Syntaxe error"<<"\n";return 1;}
  if (argc==5 || argc==4) HasArg=Standard_True;
  else HasArg=Standard_False;
  
  name=argv[1];
  // Fermeture des contextes
  TheAISContext()->CloseAllContexts();
  
  
  // Il y a des arguments
  if (HasArg) {
    if (!GetMapOfAIS().IsBound2(argv[2] ) ) {di<<"vplane: error 1st name doesn't exist in the GetMapOfAIS()."<<"\n";return 1;}
    // on recupere la shape dans la map
    Handle(AIS_InteractiveObject) theShapeA = GetMapOfAIS().Find2(argv[2] );
    
    // Le premier argument est un AIS_Point 1
    if (theShapeA->Type()==AIS_KOI_Datum && theShapeA->Signature()==1) {
      // le deuxieme argument doit etre un AIS_Point aussi
      if (argc<5 || !GetMapOfAIS().IsBound2(argv[3] ) ) {di<<"vplane: error 2de name doesn't exist in the GetMapOfAIS()."<<"\n";return 1;}
      // on recupere la shape dans la map
      Handle(AIS_InteractiveObject) theShapeB = GetMapOfAIS().Find2(argv[3] );
      // si B n'est pas un AIS_Point
      if (!(theShapeB->Type()==AIS_KOI_Datum && theShapeB->Signature()==1) ) {di<<"vplane: error 2de object is expected to be an AIS_Point. "<<"\n";return 1;  }
      // le troisieme objet est un AIS_Point
      if (!GetMapOfAIS().IsBound2(argv[4]) ) {di<<"vplane: error 3de name doesn't exist in the GetMapOfAIS()."<<"\n";return 1; }
      // on recupere la shape dans la map
      Handle(AIS_InteractiveObject) theShapeC = GetMapOfAIS().Find2(argv[4] );
      // si C n'est pas un AIS_Point
      if (!(theShapeC->Type()==AIS_KOI_Datum && theShapeC->Signature()==1) ) {di<<"vplane: error 3de object is expected to be an AIS_Point. "<<"\n";return 1;  }
      
      // Traitement des objets A,B,C 
      // Downcaste de AIS_IO en AIS_Point
      Handle(AIS_Point) theAISPointA= *(Handle(AIS_Point)*)& theShapeA;
      Handle(AIS_Point) theAISPointB= *(Handle(AIS_Point)*)& theShapeB;
      Handle(AIS_Point) theAISPointC= *(Handle(AIS_Point)*)& theShapeC;
      
       Handle(Geom_Point ) myGeomPointA=  theAISPointA->Component();
      Handle(Geom_CartesianPoint ) myCartPointA= *((Handle(Geom_CartesianPoint)*)&  myGeomPointA);
//      Handle(Geom_CartesianPoint ) myCartPointA= *(Handle(Geom_CartesianPoint)*)& (theAISPointA->Component() ) ;

       Handle(Geom_Point ) myGeomPointB =  theAISPointB->Component();
      Handle(Geom_CartesianPoint ) myCartPointB= *((Handle(Geom_CartesianPoint)*)&  theAISPointB);
//      Handle(Geom_CartesianPoint ) myCartPointB= *(Handle(Geom_CartesianPoint)*)& (theAISPointB->Component() ) ;

       Handle(Geom_Point ) myGeomPointBC=  theAISPointC->Component();
      Handle(Geom_CartesianPoint ) myCartPointC= *((Handle(Geom_CartesianPoint)*)&  theAISPointC);
//      Handle(Geom_CartesianPoint ) myCartPointC= *(Handle(Geom_CartesianPoint)*)& (theAISPointC->Component() ) ;
      
      // Verification que les 3 points sont bien differents.
      if (myCartPointB->X()==myCartPointA->X() && myCartPointB->Y()==myCartPointA->Y() && myCartPointB->Z()==myCartPointA->Z() ) {
	// B=A
	di<<"vplane error: same points"<<"\n";return 1;
      }
      if (myCartPointC->X()==myCartPointA->X() && myCartPointC->Y()==myCartPointA->Y() && myCartPointC->Z()==myCartPointA->Z() ) {
	// C=A
	di<<"vplane error: same points"<<"\n";return 1;
      }
      if (myCartPointC->X()==myCartPointB->X() && myCartPointC->Y()==myCartPointB->Y() && myCartPointC->Z()==myCartPointB->Z() ) {
	// C=B
	di<<"vplane error: same points"<<"\n";return 1;
      }
      
      gp_Pnt A= myCartPointA->Pnt();
      gp_Pnt B= myCartPointB->Pnt();
      gp_Pnt C= myCartPointC->Pnt();
      
      // Construction de l'AIS_Plane
      GC_MakePlane MkPlane (A,B,C);
      Handle(Geom_Plane) myGeomPlane = MkPlane.Value();
      Handle(AIS_Plane)  myAISPlane = new AIS_Plane(myGeomPlane );
      GetMapOfAIS().Bind (myAISPlane,name );
      TheAISContext()->Display(myAISPlane);
      
      
    }
    
    // si le premier argument est un AIS_Axis 2 
    // creation d'un plan orthogonal a l'axe passant par un point
    else if (theShapeA->Type()==AIS_KOI_Datum && theShapeA->Signature()==2 ) {
      // le deuxieme argument doit etre un AIS_Point
      if (argc!=4 || !GetMapOfAIS().IsBound2(argv[3] ) ) {di<<"vplane: error 2de name doesn't exist in the GetMapOfAIS()."<<"\n";return 1;}
      // on recupere la shape dans la map
      Handle(AIS_InteractiveObject) theShapeB = GetMapOfAIS().Find2(argv[3] );
      // si B n'est pas un AIS_Point
      if (!(theShapeB->Type()==AIS_KOI_Datum && theShapeB->Signature()==1) ) {di<<"vplane: error 2de object is expected to be an AIS_Point. "<<"\n";return 1;  }
      
      // Traitement des objets A et B 
      Handle(AIS_Axis) theAISAxisA= *(Handle(AIS_Axis)*)& theShapeA;
      Handle(AIS_Point) theAISPointB= *(Handle(AIS_Point)*)& theShapeB;
      
      Handle(Geom_Line ) myGeomLineA = theAISAxisA ->Component();
      Handle(Geom_Point) myGeomPointB= theAISPointB->Component()  ;
      
      gp_Ax1 myAxis= myGeomLineA->Position();
      Handle(Geom_CartesianPoint ) myCartPointB= *(Handle(Geom_CartesianPoint )*)& myGeomPointB;
      
      // Pas de moyens de verifier que le point B n'est pas sur l'axe
      
      gp_Dir D=myAxis.Direction();
      gp_Pnt B= myCartPointB->Pnt();
      
      // Construction de l'AIS_Plane
      Handle(Geom_Plane) myGeomPlane= new Geom_Plane(B,D);
      Handle(AIS_Plane)  myAISPlane = new AIS_Plane(myGeomPlane,B );
      GetMapOfAIS().Bind (myAISPlane,name );
      TheAISContext()->Display(myAISPlane);
      
    }
    // Si le premier argument est un AIS_Plane 7
    // Creation d'un Plan parallele a ce plan passant par le point
    else if (theShapeA->Type()==AIS_KOI_Datum && theShapeA->Signature()==7 ) {
      // le deuxieme argument doit etre un AISPoint
      if (argc!=4 || !GetMapOfAIS().IsBound2(argv[3] ) ) {di<<"vplane: error 2de name doesn't exist in the GetMapOfAIS()."<<"\n";return 1;}
      // on recupere la shape dans la map
      Handle(AIS_InteractiveObject) theShapeB = GetMapOfAIS().Find2(argv[3] );
      // si B n'est pas un AIS_Point
      if (!(theShapeB->Type()==AIS_KOI_Datum && theShapeB->Signature()==1) ) {di<<"vplane: error 2de object is expected to be an AIS_Point. "<<"\n";return 1;  }
      
      // Traitement des objets A et B 
      Handle(AIS_Plane) theAISPlaneA= *(Handle(AIS_Plane)*)& theShapeA;
      Handle(AIS_Point) theAISPointB= *(Handle(AIS_Point)*)& theShapeB;
      
      Handle (Geom_Plane) theNewGeomPlane= theAISPlaneA->Component();
      Handle(Geom_Point) myGeomPointB= theAISPointB->Component()  ;
      
      Handle(Geom_CartesianPoint ) myCartPointB= *(Handle(Geom_CartesianPoint )*)& myGeomPointB;
      gp_Pnt B= myCartPointB->Pnt();
      
      // Construction de l'AIS_Plane
      Handle(AIS_Plane)  myAISPlane = new AIS_Plane(theNewGeomPlane,B );
      GetMapOfAIS().Bind (myAISPlane,name );
      TheAISContext()->Display(myAISPlane);

    }
    // Sinon erreur
    else {di<<"vplane: error 1st object is not an AIS. "<<"\n";return 1;}
    
  }
  
  // Il n'y a pas d'arguments
  else {
    
    // Fonction vplane
    // Teste le constructeur AIS_Plane::AIS_Plane(Geom_Plane, Standard_Boolean )
    if (!strcasecmp(argv[0] ,"vplane" ) ) {
      TheAISContext()->OpenLocalContext();
      myCurrentIndex=TheAISContext()->IndexOfCurrentLocal();
      
      // Active les modes Vertex, Edge et Face
      TheAISContext()->ActivateStandardMode (AIS_Shape::SelectionType(1) );
      TheAISContext()->ActivateStandardMode (AIS_Shape::SelectionType(2) );
      TheAISContext()->ActivateStandardMode (AIS_Shape::SelectionType(4) );
      di<<"Select a vertex, a face or an edge. "<<"\n";
      
      // Boucle d'attente waitpick.
      Standard_Integer argcc = 5;
      char *buff[] = { "VPick", "X", "VPickY","VPickZ", "VPickShape" };
      char **argvv = buff;
      while (ViewerMainLoop( argcc, argvv) ) { }
      // fin de la boucle
      
      TopoDS_Shape ShapeA;
      for(TheAISContext()->InitSelected() ;TheAISContext()->MoreSelected() ;TheAISContext()->NextSelected() ) {
	ShapeA = TheAISContext()->SelectedShape();
      }
      
      // ShapeA est un Vertex
      if (ShapeA.ShapeType()==TopAbs_VERTEX ) {
	TheAISContext()->DeactivateStandardMode (AIS_Shape::SelectionType(4) );
	di<<" Select an edge or a different vertex."<<"\n";
	
	// Boucle d'attente waitpick.
	Standard_Integer argccc = 5;
	char *bufff[] = { "VPick", "X", "VPickY","VPickZ", "VPickShape" };
	char **argvvv = bufff;
	while (ViewerMainLoop( argccc, argvvv) ) { }
	// fin de la boucle
	
	TopoDS_Shape ShapeB;
	for(TheAISContext()->InitSelected() ;TheAISContext()->MoreSelected() ;TheAISContext()->NextSelected() ) {
	  ShapeB = TheAISContext()->SelectedShape();
	}
	// ShapeB est un Vertex
	if (ShapeB.ShapeType()==TopAbs_VERTEX ) {
	  // Si A et B sont le meme point
	  if (ShapeB.IsSame(ShapeA) ) {di<<" vplane: error, same points selected"<<"\n";return 1; }
	  TheAISContext()->DeactivateStandardMode (AIS_Shape::SelectionType(2) );
	  di<<" Select a different vertex."<<"\n";
	  
	  // Boucle d'attente waitpick.
	  Standard_Integer argcccc = 5;
	  char *buffff[] = { "VPick", "X", "VPickY","VPickZ", "VPickShape" };
	  char **argvvvv = buffff;
	  while (ViewerMainLoop( argcccc, argvvvv) ) { }
	  // fin de la boucle
	  
	  TopoDS_Shape ShapeC;
	  for(TheAISContext()->InitSelected() ;TheAISContext()->MoreSelected() ;TheAISContext()->NextSelected() ) {
	    ShapeC = TheAISContext()->SelectedShape();
	  }
	  // ShapeC est aussi un vertex...
	  if (ShapeC.IsSame(ShapeA)||ShapeC.IsSame(ShapeB) ) {di<<" vplane: error, same points selected"<<"\n";return 1; }
	  
	  // Fermeture du contexte local 
	  TheAISContext()->CloseLocalContext(myCurrentIndex);
	  
	  // Construction du plane 
	  gp_Pnt A=BRep_Tool::Pnt(TopoDS::Vertex(ShapeA ) );
	  gp_Pnt B=BRep_Tool::Pnt(TopoDS::Vertex(ShapeB ) );
	  gp_Pnt C=BRep_Tool::Pnt(TopoDS::Vertex(ShapeC ) );
	  GC_MakePlane MkPlane(A,B,C);
	  Handle(Geom_Plane) theGeomPlane=MkPlane.Value();
	  Handle(AIS_Plane) myAISPlane=new AIS_Plane (theGeomPlane );
	  GetMapOfAIS().Bind (myAISPlane ,name );
	  TheAISContext()->Display(myAISPlane);
	  
	}
	// ShapeB est un edge
	else  {
	  // il s'agit de verifier que le  vertex ShapeA n'est pas sur l'edge ShapeB
	  TopoDS_Edge EdgeB=TopoDS::Edge(ShapeB);
	  TopoDS_Vertex VertA=TopoDS::Vertex(ShapeA);
	  
	  BRepExtrema_ExtPC OrthoProj (VertA, EdgeB );
	  if (OrthoProj.Value(1)<0.001 ) {
	    // Le vertex est sur l'edge
	    di<<" vplane: error point is on the edge."<<"\n";return 1;
	  }
	  else {
	    // le vertex n'appartient pes a l'edge on peut construire le plane
	    // Fermeture du contexte local 
	    TheAISContext()->CloseLocalContext(myCurrentIndex);
	    // Construction du plane 
	    gp_Pnt A=BRep_Tool::Pnt(VertA );
	    TopoDS_Vertex VBa,VBb;
	    TopExp::Vertices(EdgeB ,VBa ,VBb );
	    gp_Pnt Ba=BRep_Tool::Pnt(VBa);
	    gp_Pnt Bb=BRep_Tool::Pnt(VBb);
	    GC_MakePlane MkPlane (A,Ba,Bb);
	    Handle(Geom_Plane) theGeomPlane=MkPlane.Value();
	    Handle(AIS_Plane) myAISPlane=new AIS_Plane (theGeomPlane );
	    GetMapOfAIS().Bind (myAISPlane ,name );
	    TheAISContext()->Display(myAISPlane);
	    
	  }
	  
	}
	
      }
      // ShapeA est un edge
      else if (ShapeA.ShapeType()==TopAbs_EDGE ) {
	
	TheAISContext()->DeactivateStandardMode (AIS_Shape::SelectionType(4) );
	TheAISContext()->DeactivateStandardMode (AIS_Shape::SelectionType(2) );
	di<<" Select a vertex that don't belong to the edge."<<"\n";
	
	// Boucle d'attente waitpick.
	Standard_Integer argccc = 5;
	char *bufff[] = { "VPick", "X", "VPickY","VPickZ", "VPickShape" };
	char **argvvv = bufff;
	while (ViewerMainLoop( argccc, argvvv) ) { }
	// fin de la boucle
	
	TopoDS_Shape ShapeB;
	for(TheAISContext()->InitSelected() ;TheAISContext()->MoreSelected() ;TheAISContext()->NextSelected() ) {
	  ShapeB = TheAISContext()->SelectedShape();
	}
	// ShapeB est forcement un Vertex
	// On verifie que le vertex ShapeB n'est pas sur l'edge ShapeA
	TopoDS_Edge EdgeA=TopoDS::Edge(ShapeA);
	TopoDS_Vertex VertB=TopoDS::Vertex(ShapeB);
	  
	BRepExtrema_ExtPC OrthoProj (VertB,EdgeA );
	if (OrthoProj.Value(1)<0.001 ) {
	  // Le vertex est sur l'edge
	  di<<" vplane: error point is on the edge."<<"\n";return 1;
	}
	else {
	  // le vertex n'appartient pas a l'edge on peut construire le plane
	  // Fermeture du contexte local 
	  TheAISContext()->CloseLocalContext(myCurrentIndex);
	  // Construction du plane 
	  gp_Pnt B=BRep_Tool::Pnt(VertB );
	  TopoDS_Vertex VAa,VAb;
	  TopExp::Vertices(EdgeA ,VAa ,VAb );
	  gp_Pnt Aa=BRep_Tool::Pnt(VAa);
	  gp_Pnt Ab=BRep_Tool::Pnt(VAb);
	  GC_MakePlane MkPlane (B,Aa,Ab);
	  Handle(Geom_Plane) theGeomPlane=MkPlane.Value();
	  Handle(AIS_Plane) myAISPlane=new AIS_Plane (theGeomPlane );
	  GetMapOfAIS().Bind (myAISPlane ,name );
	  TheAISContext()->Display(myAISPlane);
	  
	}
	
	
      }
      // ShapeA est une Face
      else {
	// Fermeture du contexte local: Plus rien a selectionner
	TheAISContext()->CloseLocalContext(myCurrentIndex);
	// Construction du plane 
	TopoDS_Face myFace=TopoDS::Face(ShapeA);
	BRepAdaptor_Surface mySurface (myFace, Standard_False );
	if (mySurface.GetType()==GeomAbs_Plane ) {
	  gp_Pln myPlane=mySurface.Plane();
	  Handle(Geom_Plane) theGeomPlane=new Geom_Plane (myPlane );
	  Handle(AIS_Plane) myAISPlane=new AIS_Plane (theGeomPlane );
	  GetMapOfAIS().Bind (myAISPlane ,name );
	  TheAISContext()->Display(myAISPlane);
	  
	}
	else {
	  di<<" vplane: error"<<"\n";return 1;
	}
	
      }
      
    }
    
    // Fonction vPlanePara
    // ===================
    // teste le constructeur AIS_Plane::AIS_Plane(Geom_Plane,gp_Pnt )
    else if (!strcasecmp(argv[0] ,"vplanepara" )) {
      
      TheAISContext()->OpenLocalContext();
      myCurrentIndex=TheAISContext()->IndexOfCurrentLocal();
      
      // Active les modes Vertex et Face 
      TheAISContext()->ActivateStandardMode (AIS_Shape::SelectionType(1) );
      TheAISContext()->ActivateStandardMode (AIS_Shape::SelectionType(4) );
      di<<" Select a vertex or a face."<<"\n";
      
      // Boucle d'attente waitpick.
      Standard_Integer argcc = 5;
      char *buff[] = { "VPick", "X", "VPickY","VPickZ", "VPickShape" };
      char **argvv = buff;
      while (ViewerMainLoop( argcc, argvv) ) { }
      // fin de la boucle
      
      TopoDS_Shape ShapeA;
      for(TheAISContext()->InitSelected() ;TheAISContext()->MoreSelected() ;TheAISContext()->NextSelected() ) {
	ShapeA = TheAISContext()->SelectedShape();
      }
      
      if (ShapeA.ShapeType()==TopAbs_VERTEX ) {
	// ShapeA est un vertex
	// On desactive le mode Vertex
	TheAISContext()->DeactivateStandardMode (AIS_Shape::SelectionType(1) );
	di<<" Select a face."<<"\n";
	
	// Boucle d'attente waitpick.
	Standard_Integer argccc = 5;
	char *bufff[] = { "VPick", "X", "VPickY","VPickZ", "VPickShape" };
	char **argvvv = bufff;
	while (ViewerMainLoop( argccc, argvvv) ) { }
	// fin de la boucle
	
	TopoDS_Shape ShapeB;
	for(TheAISContext()->InitSelected() ;TheAISContext()->MoreSelected() ;TheAISContext()->NextSelected() ) {
	  // Le vertex ShapeA peut etre dans la Face ShapeB
	  ShapeB = TheAISContext()->SelectedShape();
	}
	
	// Fermeture du context local
	TheAISContext()->CloseLocalContext(myCurrentIndex);
	
	// Construction du plane 
	gp_Pnt A=BRep_Tool::Pnt(TopoDS::Vertex(ShapeA ) );
	
	TopoDS_Face myFace=TopoDS::Face(ShapeB);
	BRepAdaptor_Surface mySurface (myFace, Standard_False );
	if (mySurface.GetType()==GeomAbs_Plane ) {
	  gp_Pln myPlane=mySurface.Plane();
	  // construit un plan parallele a theGeomPlane passant par A
	  myPlane.SetLocation(A);
	  Handle(Geom_Plane) theGeomPlane=new Geom_Plane (myPlane );
	  Handle(AIS_Plane) myAISPlane=new AIS_Plane (theGeomPlane ,A );
	  GetMapOfAIS().Bind (myAISPlane ,name );
	  TheAISContext()->Display(myAISPlane);
	  
	}
	else {
	  di<<" vplane: error"<<"\n";return 1;
	}
	
	
      }
      else{
	// ShapeA est une Face
	// On desactive le mode Face
	TheAISContext()->DeactivateStandardMode (AIS_Shape::SelectionType(4) );
	di<<" Select a vertex."<<"\n";
	
	// Boucle d'attente waitpick.
	Standard_Integer argccc = 5;
	char *bufff[] = { "VPick", "X", "VPickY","VPickZ", "VPickShape" };
	char **argvvv = bufff;
	while (ViewerMainLoop( argccc, argvvv) ) { }
	// fin de la boucle
	
	TopoDS_Shape ShapeB;
	for(TheAISContext()->InitSelected() ;TheAISContext()->MoreSelected() ;TheAISContext()->NextSelected() ) {
	  // Le vertex ShapeB peut etre dans la Face ShapeA
	  ShapeB = TheAISContext()->SelectedShape();
	}
	// Fermeture du context local
	TheAISContext()->CloseLocalContext(myCurrentIndex);
	
	// Construction du plane 
	gp_Pnt B=BRep_Tool::Pnt(TopoDS::Vertex(ShapeB ) );
	
	TopoDS_Face myFace=TopoDS::Face(ShapeA);
	BRepAdaptor_Surface mySurface (myFace, Standard_False );
	if (mySurface.GetType()==GeomAbs_Plane ) {
	  gp_Pln myPlane=mySurface.Plane();
	  myPlane.SetLocation(B);
	  Handle(Geom_Plane) theGeomPlane=new Geom_Plane (myPlane );
	  // construit un plan parallele a theGeomPlane passant par B
	  Handle(AIS_Plane) myAISPlane=new AIS_Plane (theGeomPlane ,B );
	  GetMapOfAIS().Bind (myAISPlane ,name );
	  TheAISContext()->Display(myAISPlane);
	  
	}
	else {
	  di<<" vplane: error"<<"\n";return 1;
	}
	
      }
      
    }
   
    // Fonction vplaneortho
    // ====================
    // teste le constructeur AIS_Plane::AIS_Plane(Geom_Plane,gp_Pnt,gp_Pnt,gp_Pnt)
    else {
      
      TheAISContext()->OpenLocalContext();
      myCurrentIndex=TheAISContext()->IndexOfCurrentLocal();
      
      // Active les modes Edge et Face 
      TheAISContext()->ActivateStandardMode (AIS_Shape::SelectionType(2) );
      TheAISContext()->ActivateStandardMode (AIS_Shape::SelectionType(4) );
      di<<" Select a face and an edge coplanar."<<"\n";
      
      // Boucle d'attente waitpick.
      Standard_Integer argcc = 5;
      char *buff[] = { "VPick", "X", "VPickY","VPickZ", "VPickShape" };
      char **argvv = buff;
      while (ViewerMainLoop( argcc, argvv) ) { }
      // fin de la boucle
      
      TopoDS_Shape ShapeA;
      for(TheAISContext()->InitSelected() ;TheAISContext()->MoreSelected() ;TheAISContext()->NextSelected() ) {
	ShapeA = TheAISContext()->SelectedShape();
      }
      
      if (ShapeA.ShapeType()==TopAbs_EDGE ) {
	// ShapeA est un edge, on desactive le mode edge...
	TheAISContext()->DeactivateStandardMode (AIS_Shape::SelectionType(2) );
	di<<" Select a face."<<"\n";
	
	// Boucle d'attente waitpick.
	Standard_Integer argccc = 5;
	char *bufff[] = { "VPick", "X", "VPickY","VPickZ", "VPickShape" };
	char **argvvv = bufff;
	while (ViewerMainLoop( argccc, argvvv) ) { }
	// fin de la boucle
	
	TopoDS_Shape ShapeB;
	for(TheAISContext()->InitSelected() ;TheAISContext()->MoreSelected() ;TheAISContext()->NextSelected() ) {
	  // L'edge ShapeA peut etre dans la Face ShapeB
	  ShapeB = TheAISContext()->SelectedShape();
	}
	
	// Fermeture du context local
	TheAISContext()->CloseLocalContext(myCurrentIndex);
	
	// Construction du plane 
	TopoDS_Edge  EdgeA=TopoDS::Edge(ShapeA);
	TopoDS_Vertex VAa,VAb;
	// vi
	TopExp::Vertices(EdgeA ,VAa ,VAb );
	gp_Pnt Aa=BRep_Tool::Pnt(VAa);
	gp_Pnt Ab=BRep_Tool::Pnt(VAb);
	gp_Vec ab  (Aa,Ab);
	
	gp_Dir Dab (ab);
	// Creation de mon axe de rotation 
	gp_Ax1 myRotAxis (Aa,Dab); 
	
	TopoDS_Face myFace=TopoDS::Face(ShapeB);
	// Il faut imperativement que l'edge soit parallele a la face
	// vi
	BRepExtrema_ExtPF myHauteurA (VAa , myFace );
	BRepExtrema_ExtPF myHauteurB (VAb , myFace );
	// on compare les deux hauteurs a la tolerance pres
	if ( fabs(myHauteurA.Value(1) - myHauteurB.Value(1) )>0.1 ) {
	  // l'edge n'est pas parallele a la face 
	   di<<" vplaneOrtho error: l'edge n'est pas parallele a la face."<<"\n";return 1;
	}
	// l'edge est OK
	BRepAdaptor_Surface mySurface (myFace, Standard_False );
	if (mySurface.GetType()==GeomAbs_Plane ) {
	  gp_Pln myPlane=mySurface.Plane();
	  // On effectue une rotation d'1/2 tour autour de l'axe de rotation
	  myPlane.Rotate(myRotAxis , PI/2 );
	  
	  Handle(Geom_Plane) theGeomPlane=new Geom_Plane (myPlane );
	  // construit un plan parallele a theGeomPlane contenant l'edgeA (De centre le milieu de l'edgeA)
	  gp_Pnt theMiddle ((Aa.X()+Ab.X() )/2 ,(Aa.Y()+Ab.Y() )/2 ,(Aa.Z()+Ab.Z() )/2 );
	  Handle(AIS_Plane) myAISPlane=new AIS_Plane (theGeomPlane ,theMiddle );
	  GetMapOfAIS().Bind (myAISPlane ,name );
	  TheAISContext()->Display(myAISPlane);
	  
	}
	else {
	  di<<" vplaneOrtho: error"<<"\n";return 1;
	}
	
      }
      
      else {
	// ShapeA est une Face, on desactive le mode face.
	TheAISContext()->DeactivateStandardMode (AIS_Shape::SelectionType(4) );
	di<<" Select an edge."<<"\n";
	
	// Boucle d'attente waitpick.
	Standard_Integer argccc = 5;
	char *bufff[] = { "VPick", "X", "VPickY","VPickZ", "VPickShape" };
	char **argvvv = bufff;
	while (ViewerMainLoop( argccc, argvvv) ) { }
	// fin de la boucle
	
	TopoDS_Shape ShapeB;
	for(TheAISContext()->InitSelected() ;TheAISContext()->MoreSelected() ;TheAISContext()->NextSelected() ) {
	  // L'edge ShapeB peut etre dans la Face ShapeA
	  ShapeB = TheAISContext()->SelectedShape();
	}
	
	// Fermeture du context local
	TheAISContext()->CloseLocalContext(myCurrentIndex);
	
	// Construction du plane 
	TopoDS_Edge  EdgeB=TopoDS::Edge(ShapeB);
	TopoDS_Vertex VBa,VBb;
	TopExp::Vertices(EdgeB ,VBa ,VBb );
	gp_Pnt Ba=BRep_Tool::Pnt(VBa);
	gp_Pnt Bb=BRep_Tool::Pnt(VBb);
	gp_Vec ab  (Ba,Bb);
	gp_Dir Dab (ab);
	// Creation de mon axe de rotation 
	gp_Ax1 myRotAxis (Ba,Dab); 
	
	TopoDS_Face myFace=TopoDS::Face(ShapeA);
	// Il faut imperativement que l'edge soit parallele a la face
	BRepExtrema_ExtPF myHauteurA (VBa , myFace );
	BRepExtrema_ExtPF myHauteurB (VBb , myFace );
	// on compare les deux hauteurs a la tolerance pres
	if ( fabs(myHauteurA.Value(1) - myHauteurB.Value(1) )>0.1 ) {
	  // l'edge n'est pas parallele a la face 
	   di<<" vplaneOrtho error: l'edge n'est pas parallele a la face."<<"\n";return 1;
	}
	// l'edge est OK
	BRepAdaptor_Surface mySurface (myFace, Standard_False );
	if (mySurface.GetType()==GeomAbs_Plane ) {
	  gp_Pln myPlane=mySurface.Plane();
	  // On effectue une rotation d'1/2 tour autour de l'axe de rotation
	  myPlane.Rotate(myRotAxis , PI/2  );
	  Handle(Geom_Plane) theGeomPlane=new Geom_Plane (myPlane );
	  // construit un plan parallele a theGeomPlane contenant l'edgeA (De centre le milieu de l'edgeA)
	  gp_Pnt theMiddle ((Ba.X()+Bb.X() )/2 , (Ba.Y()+Bb.Y() )/2 , (Ba.Z()+Bb.Z() )/2 );
	  Handle(AIS_Plane) myAISPlane=new AIS_Plane (theGeomPlane ,theMiddle );
	  GetMapOfAIS().Bind (myAISPlane ,name );
	  TheAISContext()->Display(myAISPlane);
	  
	}
	else {
	  di<<" vplaneOrtho: error"<<"\n";return 1;
	}
	
	
      }
      
    }
    
  }
  return 0;
  
}


//==============================================================================
// Fonction  vline
// ---------------  Uniquement par parametre. Pas de selection dans le viewer.
//==============================================================================

//==============================================================================
//function : VLineBuilder
//purpose  : Build an AIS_Line 
//Draw arg : vline LineName  [AIS_PointName] [AIS_PointName]
//                           [Xa] [Ya] [Za]   [Xb] [Yb] [Zb]
//==============================================================================
#include <Geom_CartesianPoint.hxx>
#include <AIS_Line.hxx>


static int VLineBuilder(Draw_Interpretor& di, Standard_Integer argc, char** argv) 
{
  Standard_Integer myCurrentIndex;
  // Verifications
  if (argc!=4 && argc!=8 && argc!=2 )  {di<<"vline error: number of arguments not correct "<<"\n";return 1; }
  // Fermeture des contextes
  TheAISContext()->CloseAllContexts();
  
  // On recupere les parametres
  Handle(AIS_InteractiveObject) theShapeA;
  Handle(AIS_InteractiveObject) theShapeB;
  
  // Parametres: AIS_Point AIS_Point
  // ===============================
  if (argc==4) {
    theShapeA= GetMapOfAIS().Find2(argv[2] );
    // On verifie que c'est bien une AIS_Point
    if (theShapeA->Type()==AIS_KOI_Datum && theShapeA->Signature()==1   ) {
      // on recupere le deuxieme AIS_Point
      theShapeB= GetMapOfAIS().Find2(argv[3] );
      if (!(theShapeB->Type()==AIS_KOI_Datum && theShapeB->Signature()==1 ) ) {
	di <<"vline error: wrong type of 2de argument."<<"\n";return 1;
      }
    }
    else {di <<"vline error: wrong type of 1st argument."<<"\n";return 1; } 
    // Les deux parametres sont du bon type. On verifie que les points ne sont pas confondus
    Handle(AIS_Point) theAISPointA= *(Handle(AIS_Point)*)& theShapeA;
    Handle(AIS_Point) theAISPointB= *(Handle(AIS_Point)*)& theShapeB;
    
    Handle(Geom_Point ) myGeomPointBA=  theAISPointA->Component();
    Handle(Geom_CartesianPoint ) myCartPointA= *((Handle(Geom_CartesianPoint)*)&  myGeomPointBA);
//    Handle(Geom_CartesianPoint ) myCartPointA= *(Handle(Geom_CartesianPoint)*)& (theAISPointA->Component() ) ;

    Handle(Geom_Point ) myGeomPointB=  theAISPointB->Component();
    Handle(Geom_CartesianPoint ) myCartPointB= *((Handle(Geom_CartesianPoint)*)&  myGeomPointB);
//    Handle(Geom_CartesianPoint ) myCartPointB= *(Handle(Geom_CartesianPoint)*)& (theAISPointB->Component() ) ;
    
    if (myCartPointB->X()==myCartPointA->X() && myCartPointB->Y()==myCartPointA->Y() && myCartPointB->Z()==myCartPointA->Z() ) {
      // B=A
      di<<"vline error: same points"<<"\n";return 1;
    }
    // Les deux points sont OK...Construction de l'AIS_Line (en faite, le segment AB)
    Handle(AIS_Line) theAISLine= new AIS_Line(myCartPointA,myCartPointB );
    GetMapOfAIS().Bind(theAISLine,argv[1] );
    TheAISContext()->Display(theAISLine );
    
  }
  
  // Parametres 6 Reals
  // ==================
  
  else if (argc==8) {
    // On verifie que les deux points ne sont pas confondus 
    
    Standard_Real coord[6];
    for(Standard_Integer i=0;i<=2;i++){
      coord[i]=atof(argv[2+i]);
      coord[i+3]=atof(argv[5+i]);
    }
    
    Handle(Geom_CartesianPoint ) myCartPointA=new Geom_CartesianPoint (coord[0],coord[1],coord[2] );
    Handle(Geom_CartesianPoint ) myCartPointB=new Geom_CartesianPoint (coord[3],coord[4],coord[5] );
    
    Handle(AIS_Line) theAISLine= new AIS_Line(myCartPointA,myCartPointB );
    GetMapOfAIS().Bind(theAISLine,argv[1] );
    TheAISContext()->Display(theAISLine );
    
  }
  
  // Pas de parametres: Selection dans le viewer.
  // ============================================
  
  else {
    TheAISContext()->OpenLocalContext();
    myCurrentIndex=TheAISContext()->IndexOfCurrentLocal();
    
    // Active le mode Vertex.
    TheAISContext()->ActivateStandardMode (AIS_Shape::SelectionType(1) );
    di<<" Select a vertex "<<"\n";
    
    // Boucle d'attente waitpick.
    Standard_Integer argcc = 5;
    char *buff[] = { "VPick", "X", "VPickY","VPickZ", "VPickShape" };
    char **argvv = buff;
    while (ViewerMainLoop( argcc, argvv) ) { }
    // fin de la boucle
    
    TopoDS_Shape ShapeA;
    for(TheAISContext()->InitSelected() ;TheAISContext()->MoreSelected() ;TheAISContext()->NextSelected() ) {
      ShapeA = TheAISContext()->SelectedShape();
    }
    
    // ShapeA est un Vertex
    if (ShapeA.ShapeType()==TopAbs_VERTEX ) {
      
      di<<" Select a different vertex."<<"\n";
      
      TopoDS_Shape ShapeB;
      do {
	
	// Boucle d'attente waitpick.
	Standard_Integer argccc = 5;
	char *bufff[] = { "VPick", "X", "VPickY","VPickZ", "VPickShape" };
	char **argvvv = bufff;
	while (ViewerMainLoop( argccc, argvvv) ) { }
	// fin de la boucle 
	
	for(TheAISContext()->InitSelected() ;TheAISContext()->MoreSelected() ;TheAISContext()->NextSelected() ) {
	  ShapeB = TheAISContext()->SelectedShape();
	}
	
	
      } while(ShapeB.IsSame(ShapeA) );
      
      // Fermeture du context local
      TheAISContext()->CloseLocalContext(myCurrentIndex);
	
      // Construction de la line
      gp_Pnt   A=BRep_Tool::Pnt(TopoDS::Vertex(ShapeA)  );
      gp_Pnt   B=BRep_Tool::Pnt(TopoDS::Vertex(ShapeB)  );
      
      Handle(Geom_CartesianPoint ) myCartPointA=new Geom_CartesianPoint(A);
      Handle(Geom_CartesianPoint ) myCartPointB=new Geom_CartesianPoint(B);
      
      Handle(AIS_Line) theAISLine= new AIS_Line(myCartPointA,myCartPointB );
      GetMapOfAIS().Bind(theAISLine,argv[1] );
      TheAISContext()->Display(theAISLine );
      
    }
    else  {
      di<<"vline error."<<"\n";
    }
    
  }
  
  return 0;
}


//==============================================================================
// Fonction  vcircle
// -----------------  Uniquement par parametre. Pas de selection dans le viewer.
//==============================================================================

//==============================================================================
//function : VCircleBuilder
//purpose  : Build an AIS_Circle 
//Draw arg : vcircle CircleName PlaneName PointName Radius
//                              PointName PointName PointName
//==============================================================================
#include <Geom_CartesianPoint.hxx>
#include <Geom_Circle.hxx>
#include <AIS_Circle.hxx>
#include <GC_MakeCircle.hxx>
#include <Geom_Plane.hxx>
#include <gp_Pln.hxx>

static int VCircleBuilder(Draw_Interpretor& di, Standard_Integer argc, char** argv) 
{
  Standard_Integer myCurrentIndex;
  // verification of the arguments
  if (argc>5 ||  argc<2 ) {di<<"vcircle error: expect 3 arguments."<<"\n";return 1; }
  TheAISContext()->CloseAllContexts();
  
  // Il y a des arguments
  if (argc==5 ) {
    Handle(AIS_InteractiveObject) theShapeA;
    Handle(AIS_InteractiveObject) theShapeB;
    
    theShapeA=GetMapOfAIS().Find2(argv[2]);
    theShapeB=GetMapOfAIS().Find2(argv[3]);
    
    // Arguments: AIS_Point AIS_Point AIS_Point
    // ========================================
    if (theShapeA->Type()==AIS_KOI_Datum && theShapeA->Signature()==1 ) {
      if (theShapeB->Type()!=AIS_KOI_Datum || theShapeB->Signature()!=1 ) {
	di<<"vcircle error: 2de argument is unexpected to be a point."<<"\n";return 1; 
      }
      // Le troisieme objet doit etre un point
      Handle(AIS_InteractiveObject) theShapeC=GetMapOfAIS().Find2(argv[4]);
      if (theShapeC->Type()!=AIS_KOI_Datum || theShapeC->Signature()!=1 ) {
	di<<"vcircle error: 3de argument is unexpected to be a point."<<"\n";return 1; 
      }
      // tag
      // On verifie que les 3 points sont differents.
      Handle(AIS_Point) theAISPointA= *(Handle(AIS_Point)*)& theShapeA;
      Handle(AIS_Point) theAISPointB= *(Handle(AIS_Point)*)& theShapeB;
      Handle(AIS_Point) theAISPointC= *(Handle(AIS_Point)*)& theShapeC;
      
       Handle(Geom_Point ) myGeomPointA=  theAISPointA->Component();
      Handle(Geom_CartesianPoint ) myCartPointA= *((Handle(Geom_CartesianPoint)*)&  myGeomPointA);
//      Handle(Geom_CartesianPoint ) myCartPointA= *(Handle(Geom_CartesianPoint)*)& (theAISPointA->Component() );

       Handle(Geom_Point ) myGeomPointB =  theAISPointB->Component();
      Handle(Geom_CartesianPoint ) myCartPointB= *((Handle(Geom_CartesianPoint)*)&  theAISPointB);
//      Handle(Geom_CartesianPoint ) myCartPointB= *(Handle(Geom_CartesianPoint)*)& (theAISPointB->Component() );

       Handle(Geom_Point ) myGeomPointBC=  theAISPointC->Component();
      Handle(Geom_CartesianPoint ) myCartPointC= *((Handle(Geom_CartesianPoint)*)&  theAISPointC);
//      Handle(Geom_CartesianPoint ) myCartPointC= *(Handle(Geom_CartesianPoint)*)& (theAISPointC->Component() );
    
      // Test A=B
      if (myCartPointA->X()==myCartPointB->X() && myCartPointA->Y()==myCartPointB->Y() && myCartPointA->Z()==myCartPointB->Z()  ) {
	di<<"vcircle error: Same points."<<"\n";return 1; 
      }
      // Test A=C
      if (myCartPointA->X()==myCartPointC->X() && myCartPointA->Y()==myCartPointC->Y() && myCartPointA->Z()==myCartPointC->Z()  ) {
	di<<"vcircle error: Same points."<<"\n";return 1; 
      }
      // Test B=C
      if (myCartPointB->X()==myCartPointC->X() && myCartPointB->Y()==myCartPointC->Y() && myCartPointB->Z()==myCartPointC->Z()  ) {
	di<<"vcircle error: Same points."<<"\n";return 1; 
      }
      // Construction du cercle
      GC_MakeCircle Cir=GC_MakeCircle (myCartPointA->Pnt(),myCartPointB->Pnt(),myCartPointC->Pnt() );
      Handle (Geom_Circle) theGeomCircle=Cir.Value();
      Handle(AIS_Circle) theAISCircle=new AIS_Circle(theGeomCircle );
      GetMapOfAIS().Bind(theAISCircle,argv[1] );
      TheAISContext()->Display(theAISCircle );
    
    }
    
    // Arguments: ASI_Plane AIS_Point Real
    // ===================================
    else if (theShapeA->Type()==AIS_KOI_Datum && theShapeA->Signature()==7 ) {
      if (theShapeB->Type()!=AIS_KOI_Datum || theShapeB->Signature()!=1 ) {
	di<<"vcircle error: 2de element is a unexpected to be a point."<<"\n";return 1; 
      }
      // On verifie que le rayon est bien >=0
      if (atof(argv[4])<=0 ) {di<<"vcircle error: the radius must be >=0."<<"\n";return 1;  }
      
      // On recupere la normale au Plane.
      Handle(AIS_Plane) theAISPlane= *(Handle(AIS_Plane)*)& theShapeA;
      Handle(AIS_Point) theAISPointB= *(Handle(AIS_Point)*)& theShapeB;
      

//      Handle(Geom_Plane ) myGeomPlane= *(Handle(Geom_Plane)*)& (theAISPlane->Component() );
      Handle(Geom_Plane ) myGeomPlane= theAISPlane->Component();
       Handle(Geom_Point ) myGeomPointB =  theAISPointB->Component();
      Handle(Geom_CartesianPoint ) myCartPointB= *((Handle(Geom_CartesianPoint)*)&  theAISPointB);
//      Handle(Geom_CartesianPoint ) myCartPointB= *(Handle(Geom_CartesianPoint)*)& (theAISPointB->Component() );
      
      //Handle(Geom_Axis2Placement) OrigineAndAxii=myGeomPlane->Axis();
      gp_Pln mygpPlane = myGeomPlane->Pln();
      gp_Ax1 thegpAxe = mygpPlane.Axis();
      gp_Dir theDir = thegpAxe.Direction();
      gp_Pnt theCenter=myCartPointB->Pnt();
      Standard_Real TheR = atof(argv[4]);
      GC_MakeCircle Cir=GC_MakeCircle (theCenter, theDir ,TheR);
      Handle (Geom_Circle) theGeomCircle=Cir.Value();
      Handle(AIS_Circle) theAISCircle=new AIS_Circle(theGeomCircle );
      GetMapOfAIS().Bind(theAISCircle,argv[1] );
      TheAISContext()->Display(theAISCircle );
      
    }
    
    // Error
    else{
      di<<"vcircle error: !st argument is a unexpected type."<<"\n";return 1;
    }
    
  }
  // Pas d'arguments: selection dans le viewer
  // =========================================
  else {
    
    TheAISContext()->OpenLocalContext();
    myCurrentIndex=TheAISContext()->IndexOfCurrentLocal();
    
    // Active le mode Vertex et face.
    TheAISContext()->ActivateStandardMode (AIS_Shape::SelectionType(1) );
    TheAISContext()->ActivateStandardMode (AIS_Shape::SelectionType(4) );
    di<<" Select a vertex or a face."<<"\n";
    
    // Boucle d'attente waitpick.
    Standard_Integer argcc = 5;
    char *buff[] = { "VPick", "X", "VPickY","VPickZ", "VPickShape" };
    char **argvv = buff;
    while (ViewerMainLoop( argcc, argvv) ) { }
    // fin de la boucle
    
    TopoDS_Shape ShapeA;
    for(TheAISContext()->InitSelected() ;TheAISContext()->MoreSelected() ;TheAISContext()->NextSelected() ) {
      ShapeA = TheAISContext()->SelectedShape();
    }
    
    // ShapeA est un Vertex
    if (ShapeA.ShapeType()==TopAbs_VERTEX ) {
      TheAISContext()->DeactivateStandardMode (AIS_Shape::SelectionType(4) );
      di<<" Select a different vertex."<<"\n";
      
      TopoDS_Shape ShapeB;
      do {
	
	// Boucle d'attente waitpick.
	Standard_Integer argccc = 5;
	char *bufff[] = { "VPick", "X", "VPickY","VPickZ", "VPickShape" };
	char **argvvv = bufff;
	while (ViewerMainLoop( argccc, argvvv) ) { }
	// fin de la boucle 
	
	for(TheAISContext()->InitSelected() ;TheAISContext()->MoreSelected() ;TheAISContext()->NextSelected() ) {
	  ShapeB = TheAISContext()->SelectedShape();
	}
	
	
      } while(ShapeB.IsSame(ShapeA) );
      
      // Selection de ShapeC
      di<<" Select the last vertex."<<"\n";
      TopoDS_Shape ShapeC;
      do {
	
	// Boucle d'attente waitpick.
	Standard_Integer argcccc = 5;
	char *buffff[] = { "VPick", "X", "VPickY","VPickZ", "VPickShape" };
	char **argvvvv = buffff;
	while (ViewerMainLoop( argcccc, argvvvv) ) { }
	// fin de la boucle 
	
	for(TheAISContext()->InitSelected() ;TheAISContext()->MoreSelected() ;TheAISContext()->NextSelected() ) {
	  ShapeC = TheAISContext()->SelectedShape();
	}
	
	
      } while(ShapeC.IsSame(ShapeA) || ShapeC.IsSame(ShapeB) );
      
      // Fermeture du context local
      TheAISContext()->CloseLocalContext(myCurrentIndex);
	
      // Construction du cercle 
      gp_Pnt   A=BRep_Tool::Pnt(TopoDS::Vertex(ShapeA)  );
      gp_Pnt   B=BRep_Tool::Pnt(TopoDS::Vertex(ShapeB)  );
      gp_Pnt   C=BRep_Tool::Pnt(TopoDS::Vertex(ShapeC)  );
      
      GC_MakeCircle Cir=GC_MakeCircle (A,B,C );
      Handle (Geom_Circle) theGeomCircle=Cir.Value();
      Handle(AIS_Circle) theAISCircle=new AIS_Circle(theGeomCircle );
      GetMapOfAIS().Bind(theAISCircle,argv[1] );
      TheAISContext()->Display(theAISCircle );
      
    }
    // ShapeA est une face.
    else  {
      di<<" Select a vertex (in your face)."<<"\n";
      TheAISContext()->DeactivateStandardMode (AIS_Shape::SelectionType(4) );
      
      TopoDS_Shape ShapeB;
      // Boucle d'attente waitpick.
      Standard_Integer argccc = 5;
      char *bufff[] = { "VPick", "X", "VPickY","VPickZ", "VPickShape" };
      char **argvvv = bufff;
      while (ViewerMainLoop( argccc, argvvv) ) { }
      // fin de la boucle 
      
      for(TheAISContext()->InitSelected() ;TheAISContext()->MoreSelected() ;TheAISContext()->NextSelected() ) {
	ShapeB = TheAISContext()->SelectedShape();
      }
      
      // Recuperation du rayon.
      Standard_Integer theRad;
      do {
	di<<" Enter the value of the radius:"<<"\n";
	cin>>theRad;
      } while (theRad<=0);
      
      // Fermeture du context local
      TheAISContext()->CloseLocalContext(myCurrentIndex);
      // Construction du cercle.
      
      // On recupere la normale au Plane. tag
      TopoDS_Face myFace=TopoDS::Face(ShapeA);
      BRepAdaptor_Surface mySurface (myFace, Standard_False );
      gp_Pln myPlane=mySurface.Plane();
      Handle(Geom_Plane) theGeomPlane=new Geom_Plane (myPlane );
      gp_Pln mygpPlane = theGeomPlane->Pln();
      gp_Ax1 thegpAxe = mygpPlane.Axis();
      gp_Dir theDir = thegpAxe.Direction();
      
      // On recupere le centre.
      gp_Pnt   theCenter=BRep_Tool::Pnt(TopoDS::Vertex(ShapeB)  );
      
      // On construit l'AIS_Circle
      GC_MakeCircle Cir=GC_MakeCircle (theCenter, theDir ,theRad  );
      Handle (Geom_Circle) theGeomCircle=Cir.Value();
      Handle(AIS_Circle) theAISCircle=new AIS_Circle(theGeomCircle );
      GetMapOfAIS().Bind(theAISCircle,argv[1] );
      TheAISContext()->Display(theAISCircle );
      
    }
    
    
  }
  
  return 0;
}



//=======================================================================
//function : ObjectsCommands
//purpose  : 
//=======================================================================

void ViewerTest::ObjectCommands(Draw_Interpretor& theCommands)
{
  char *group ="AISObjects";
  theCommands.Add("vtrihedron",
		  "vtrihedron         : vtrihedron name [Xo] [Yo] [Zo] [Zu] [Zv] [Zw] [Xu] [Xv] [Xw] ",
		  __FILE__,VTrihedron,group);
  theCommands.Add("vtri2d", 
		  "vtri2d Name Selection in the viewer only ",
		  __FILE__,VTrihedron2D ,group);

  theCommands.Add("vplanetri",  
		  "vplanetri Name Selection in the viewer only ",
		  __FILE__,VPlaneTrihedron ,group);

  theCommands.Add("vsize",
		  "vsize       : vsize [name(Default=Current)] [size(Default=100)] ",
		  __FILE__,VSize,group);


  theCommands.Add("vaxis",
		  "vaxis nom [Xa] [Ya] [Za] [Xb] [Yb] [Zb]",
		  __FILE__,VAxisBuilder,group);
  
  theCommands.Add("vaxispara", 
		  "vaxispara  nom ",
		  __FILE__,VAxisBuilder,group);
  
  theCommands.Add("vaxisortho",
		  "vaxisotho  nom ",
		  __FILE__,VAxisBuilder,group);
  
  theCommands.Add("vpoint",
		  "vpoint  PointName [Xa] [Ya] [Za] ",
		  __FILE__,VPointBuilder,group);
  
  theCommands.Add("vplane",
		  "vplane  PlaneName [AxisName/PlaneName/PointName] [PointName/PointName/PointName] [Nothing/Nothing/PointName] ",
		  __FILE__,VPlaneBuilder,group);
  
  theCommands.Add("vplanepara",
		  "vplanepara  PlaneName  ",
		  __FILE__,VPlaneBuilder,group);

  theCommands.Add("vplaneortho",
		  "vplaneortho  PlaneName  ",
		  __FILE__,VPlaneBuilder,group);

  theCommands.Add("vline", 
		  "vline: vline LineName [Xa/PointName] [Ya/PointName] [Za] [Xb] [Yb] [Zb]  ",
		  __FILE__,VLineBuilder,group);
  
  theCommands.Add("vcircle",
		  "vcircle CircleName [PointName/PlaneName] [PointName] [Radius] ",
		  __FILE__,VCircleBuilder,group);
  
}
