// Created by: CKY / Contract Toubro-Larsen
// Copyright (c) 1993-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 <gp_GTrsf.hxx>
#include <gp_Pnt.hxx>
#include <gp_XYZ.hxx>
#include <IGESGeom_Plane.hxx>
#include <Standard_Type.hxx>

IMPLEMENT_STANDARD_RTTIEXT(IGESGeom_Plane,IGESData_IGESEntity)

IGESGeom_Plane::IGESGeom_Plane ()     {  }


    void IGESGeom_Plane::Init
  (const Standard_Real A, const Standard_Real B, 
   const Standard_Real C, const Standard_Real D, 
   const Handle(IGESData_IGESEntity)& aCurve, 
   const gp_XYZ& attach, const Standard_Real aSize)
{
  theA = A;
  theB = B;
  theC = C;
  theD = D;
  theCurve  = aCurve;
  theAttach = attach;
  theSize   = aSize;
  InitTypeAndForm(108,FormNumber());
// FormNumber : 0 No Curve. +1 Bound. -1 Hole
}

    void  IGESGeom_Plane::SetFormNumber (const Standard_Integer form)
{
  Standard_Integer fn = 0;
  if (form < 0) fn = -1;
  if (form > 0) fn = 1;
  InitTypeAndForm(108,fn);
}

    void IGESGeom_Plane::Equation
  (Standard_Real& A, Standard_Real& B, Standard_Real& C, Standard_Real& D) const
{
  A = theA;
  B = theB;
  C = theC;
  D = theD;
}

    Standard_Boolean IGESGeom_Plane::HasBoundingCurve () const
{
  return (!theCurve.IsNull());
}

    Standard_Boolean IGESGeom_Plane::HasBoundingCurveHole () const
{
  return ((FormNumber() == -1) && (!theCurve.IsNull()));
}

    Handle(IGESData_IGESEntity) IGESGeom_Plane::BoundingCurve () const
{
  return theCurve;
}

    Standard_Boolean IGESGeom_Plane::HasSymbolAttach () const
{
  return (theSize > 0);
}

    gp_Pnt IGESGeom_Plane::SymbolAttach () const
{
  gp_Pnt attach(theAttach);
  return attach;
}

    gp_Pnt IGESGeom_Plane::TransformedSymbolAttach () const
{
  if (theSize > 0 && HasTransf()) 
    {
      gp_XYZ Symbol = theAttach;
      Location().Transforms(Symbol);
      return gp_Pnt(Symbol);
    }
  else return gp_Pnt(0, 0, 0);
}

    Standard_Real IGESGeom_Plane::SymbolSize () const
{
  return theSize;
}

    void  IGESGeom_Plane::TransformedEquation
  (Standard_Real& A, Standard_Real& B, Standard_Real& C, Standard_Real& D) const
{
  //eqn of plane AX + BY + CZ = D

  Standard_Real x1,y1,z1,x2,y2,z2,x3,y3,z3;

  //case 1 intersection of the plane with the XY plane.
  x1 = 0.0;
  y1 = 0.0;
  z1 = theD / theC;

  //case 2 intersection of the plane with the XZ plane.
  x2 = 0.0;
  y2 = theD / theB;
  z2 = 0.0;

  //case 3 intersection of the plane with the YZ plane.
  x3 = theD / theA;
  y3 = 0.0;
  z3 = 0.0;
  gp_XYZ P1(x1,y1,z1);
  gp_XYZ P2(x2,y2,z2);
  gp_XYZ P3(x3,y3,z3);
  Location().Transforms(P1);
  Location().Transforms(P2);
  Location().Transforms(P3);
  x1 = P1.X();
  y1 = P1.Y();
  z1 = P1.Z();
  x2 = P2.X();
  y2 = P2.Y();
  z2 = P2.Z();
  x3 = P3.X();
  y3 = P3.Y();
  z3 = P3.Z();

/*
  General eqn of plane can also be written as
  a(x1 -x2) + b(y1 - y2) + c(z1 - z2) = 0
  a(x3 - x2) + b(y3 - y2) + c(z3 -z2) = 0 
  Applying Cramer's Rule :
  a                       b                       c               
  -------------   =   ---------------     =    ---------------   =   k
  |y3-y2  z3-z2|      |z3-z2   x3-x2|          |x3-x2   y3-y2|
  |y1-y2  z1-z2|      |z1-z2   x1-x2|          |x1-x2   y1-y2|

  .
  . .  a = c1*k , b = c2*k , c = c3*k
  hence c1(x - x2) + c2(y - y2) + c3(z - z2) = 0

*/
  Standard_Real c1,c2,c3;

  c1 = (y1*(-z3 + z2) + y2*(-z1 + z3) + y3*(z1 - z2));
  c2 = (x1*(z3 - z2) + x2*(-z3 + z1) + x3*(-z1 + z2));
  c3 = (x1*(-y3 + y2) + x2*(-y1 + y3) + x3*(y1 - y2));

  A = c1;
  B = c2;
  C = c3;
  D = c1*x2 + c2*y2 + c3*z3;
}
