// Created on: 1996-03-18
// Created by: Flore Lantheaume
// Copyright (c) 1996-1999 Matra Datavision
// Copyright (c) 1999-2014 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.

#include <DsgPrs_ConcentricPresentation.hxx>
#include <ElCLib.hxx>
#include <gp_Circ.hxx>
#include <gp_Dir.hxx>
#include <gp_Pnt.hxx>
#include <gp_Vec.hxx>
#include <Graphic3d_ArrayOfPolylines.hxx>
#include <Graphic3d_Group.hxx>
#include <Prs3d_DimensionAspect.hxx>
#include <Prs3d_LineAspect.hxx>
#include <Prs3d_Presentation.hxx>

void DsgPrs_ConcentricPresentation::Add(const Handle(Prs3d_Presentation)& aPresentation,
                                        const Handle(Prs3d_Drawer)&       aDrawer,
                                        const gp_Pnt&                     aCenter,
                                        const Standard_Real               aRadius,
                                        const gp_Dir&                     aNorm,
                                        const gp_Pnt&                     aPoint)
{
  Handle(Prs3d_DimensionAspect) LA = aDrawer->DimensionAspect();

  // Creation et discretisation du plus gros cercle
  gp_Circ                Circ(gp_Ax2(aCenter, aNorm), aRadius);
  const Standard_Integer nbp   = 50;
  const Standard_Real    dteta = (2. * M_PI) / nbp;

  aPresentation->CurrentGroup()->SetPrimitivesAspect(LA->LineAspect()->Aspect());

  Handle(Graphic3d_ArrayOfPolylines) aPrims = new Graphic3d_ArrayOfPolylines(2 * nbp + 6, 4);

  gp_Pnt pt1 = ElCLib::Value(0., Circ);
  aPrims->AddBound(nbp + 1);
  aPrims->AddVertex(pt1);
  Standard_Real    ucur = dteta;
  Standard_Integer i;
  for (i = 2; i <= nbp; i++, ucur += dteta)
    aPrims->AddVertex(ElCLib::Value(ucur, Circ));
  aPrims->AddVertex(pt1);

  // Creation et discretisation du plus petit cercle
  Circ.SetRadius(0.5 * aRadius);
  pt1 = ElCLib::Value(0., Circ);
  aPrims->AddBound(nbp + 1);
  aPrims->AddVertex(pt1);
  ucur = dteta;
  for (i = 2; i <= nbp; i++, ucur += dteta)
    aPrims->AddVertex(ElCLib::Value(ucur, Circ));
  aPrims->AddVertex(pt1);

  // Creation de la croix
  // 1er segment
  gp_Dir vecnorm(aPoint.XYZ() - aCenter.XYZ());
  gp_Vec vec(vecnorm);
  vec.Multiply(aRadius);
  gp_Pnt p1 = aCenter.Translated(vec);
  gp_Pnt p2 = aCenter.Translated(-vec);

  aPrims->AddBound(2);
  aPrims->AddVertex(p1);
  aPrims->AddVertex(p2);

  // 2ieme segment
  vec.Cross(aNorm);
  vecnorm.SetCoord(vec.X(), vec.Y(), vec.Z());
  vec.SetXYZ(vecnorm.XYZ());
  vec.Multiply(aRadius);
  p1 = aCenter.Translated(vec);
  p2 = aCenter.Translated(-vec);

  aPrims->AddBound(2);
  aPrims->AddVertex(p1);
  aPrims->AddVertex(p2);

  aPresentation->CurrentGroup()->AddPrimitiveArray(aPrims);
}
