// File:	DBRep_8.cxx
// Created:	Fri Feb 18 17:24:52 1994
// Author:	Remi LEQUETTE
//		<rle@nonox>

#include <Standard_Stream.hxx>
#include <BRepTest.hxx>
#include <Draw_Interpretor.hxx>
#include <Draw_Appli.hxx>
#include <DBRep.hxx>
#include <BRepGProp.hxx>
#include <TopoDS_Shape.hxx>
#include <GProp_PrincipalProps.hxx>
#include <gp_Ax2.hxx>
#include <gp_Ax3.hxx>

#include <Draw_Axis3D.hxx>
#include <Precision.hxx>

#ifdef WNT
Standard_IMPORT Draw_Viewer dout;
#endif


Standard_Integer props(Draw_Interpretor& di, Standard_Integer n, char** a)
{
  if (n < 2) {
    di << "Use: " << a[0] << " shape [epsilon] [c[losed]] [x y z]" << "\n";
    di << "Compute properties of the shape" << "\n";
    di << "The epsilon, if given, defines relative precision of computation" << "\n";
    di << "The \"closed\" flag, if present, do computation only closed shells of the shape" << "\n";
    di << "The centroid coordinates will be put to DRAW variables x y z (if given)\n" << "\n";
    return 1;
  }

  TopoDS_Shape S = DBRep::Get(a[1]);
  if (S.IsNull()) return 0;

  GProp_GProps G;

  Standard_Boolean onlyClosed = Standard_False;
  Standard_Real eps = 1.0;
  Standard_Boolean witheps = Standard_False;
  if(n > 2 && *a[2]=='c' || n > 3 && *a[3]=='c') onlyClosed = Standard_True;
  if(n > 2 && *a[2]!='c' && n != 5) {eps = atof (a[2]); witheps = Standard_True;}

  if (witheps){
    if (Abs(eps) < Precision::Angular()) return 2;
    if (*a[0] == 'l')
      BRepGProp::LinearProperties(S,G);
    else if (*a[0] == 's')
      eps = BRepGProp::SurfaceProperties(S,G,eps);
    else 
      eps = BRepGProp::VolumeProperties(S,G,eps,onlyClosed);
  }
  else {
    if (*a[0] == 'l')
      BRepGProp::LinearProperties(S,G);
    else if (*a[0] == 's')
      BRepGProp::SurfaceProperties(S,G);
    else 
      BRepGProp::VolumeProperties(S,G,onlyClosed);
  }
  
  gp_Pnt P = G.CentreOfMass();
  gp_Mat I = G.MatrixOfInertia();

  if (n >= 5) {
    Standard_Integer shift =  n - 5;
    Draw::Set(a[shift+2],P.X());
    Draw::Set(a[shift+3],P.Y());
    Draw::Set(a[shift+4],P.Z());
  }
	    
  Standard_SStream aSStream1;
  aSStream1 << "\n\n";
  aSStream1 << "Mass : " << setw(15) << G.Mass() << "\n" << "\n";
  if(witheps && *a[0] != 'l') aSStream1 << "Relative error of mass computation : " <<  setw(15) << eps <<  "\n" << "\n";
  
  aSStream1 << "Center of gravity : \n";
  aSStream1 << "X = " << setw(15) << P.X() << "\n";
  aSStream1 << "Y = " << setw(15) << P.Y() << "\n";
  aSStream1 << "Z = " << setw(15) << P.Z() << "\n";
  aSStream1 << "\n";
  
  aSStream1 << "Matrix of Inertia : \n";
  aSStream1 << setw(15) << I(1,1);
  aSStream1 << " " << setw(15) << I(1,2);
  aSStream1 << " " << setw(15) << I(1,3) << "\n";
  aSStream1 << setw(15) << I(2,1);
  aSStream1 << " " << setw(15) << I(2,2);
  aSStream1 << " " << setw(15) << I(2,3) << "\n";
  aSStream1 << setw(15) << I(3,1);
  aSStream1 << " " << setw(15) << I(3,2);
  aSStream1 << " " << setw(15) << I(3,3) << "\n";
  aSStream1 << "\n";
  aSStream1 << ends;
  di << GetSString(aSStream1);

  GProp_PrincipalProps Pr = G.PrincipalProperties();

  Standard_Real Ix,Iy,Iz;
  Pr.Moments(Ix,Iy,Iz);
  
  Standard_SStream aSStream2;
  aSStream2 << "Moments : \n";
  aSStream2 << "IX = " << setw(15) << Ix << "\n";
  aSStream2 << "IY = " << setw(15) << Iy << "\n";
  aSStream2 << "IZ = " << setw(15) << Iz << "\n";
  aSStream2 << "\n";
  aSStream2 << ends;
  di << GetSString(aSStream2);

  if (n == 2) {  
    gp_Ax2 axes(P,Pr.ThirdAxisOfInertia(),Pr.FirstAxisOfInertia());
    
    Handle(Draw_Axis3D) Dax = new Draw_Axis3D(axes,Draw_orange,30);
    dout << Dax;
  }

  return 0;
}


//=======================================================================
//function : GPropCommands
//purpose  : 
//=======================================================================

void  BRepTest::GPropCommands(Draw_Interpretor& theCommands)
{
  static Standard_Boolean done = Standard_False;
  if (done) return;
  done = Standard_True;

  DBRep::BasicCommands(theCommands);

  char* g = "Global properties";
  theCommands.Add("lprops",
		  "lprops name [epsilon] [x y z] : compute linear properties",
		  __FILE__,
		  props,
		  g);
  theCommands.Add("sprops",
		  "sprops name [epsilon] [x y z] : compute surfacic properties",
		  __FILE__,
		  props,
		  g);
  theCommands.Add("vprops",
		  "vprops name [epsilon] [c[losed]] [x y z] : compute volumic properties",
		  __FILE__,
		  props,
		  g);
}
