#include "TMath.h"
#include "hkaldef.h"
#include "hkalgeomtools.h"
#include "hkalplane.h"
#include <iostream>
#include <iomanip>
using namespace std;
ClassImp(HKalPlane)
HKalPlane::HKalPlane(const TVector3 ¢er, const TVector3 &normal) : TObject() {
    
    
    
    
    setPlane(center, normal);
}
HKalPlane::HKalPlane(const TVector3 &origin, const TVector3 &u, const TVector3 &v) : TObject() {
    
    
    setPlane(origin, u, v);
}
HKalPlane::~HKalPlane() {
}
Double_t HKalPlane::distanceToPlane(const TVector3 &point) const {
    
    return HKalGeomTools::distancePointToPlane(point, getCenter(), getNormal());
}
Bool_t HKalPlane::findIntersection(TVector3 &pointIntersect, const TVector3 &pos, const TVector3 &dir) const {
    
    
    
    
    
    return HKalGeomTools::findIntersectionLinePlane(pointIntersect, pos, dir, getCenter(), getNormal());
}
Bool_t HKalPlane::isOnSurface(const TVector3 &point) const {
    
    return HKalGeomTools::isPointOnPlane(point, getCenter(), getNormal());
}
void HKalPlane::print(Option_t* opt) const {
    
    
    cout<<"**** Properties of plane: ****"<<endl;
    cout<<"Center of layer: "<<endl;
    getCenter().Print();
    cout<<"Normal of layer:"<<endl;
    getNormal().Print();
    cout<<"Axis U:"<<endl;
    getAxisU().Print();
    cout<<"Axis V:"<<endl;
    getAxisV().Print();
    cout<<"**** End print of plane ****"<<endl;
}
Double_t HKalPlane::signedDistanceToPlane(const TVector3 &point) const {
    
    
    
    return HKalGeomTools::signedDistancePointToPlane(point, getCenter(), getNormal());
}
void HKalPlane::transform(const TRotation &transMat) {
    
    vCenter.Transform(transMat);
    vNormal.Transform(transMat);
    vAxisU .Transform(transMat);
    vAxisV .Transform(transMat);
}
Bool_t HKalPlane::setPlane(const TVector3 &origin, const TVector3 &normal) {
    
#if kalDebug > 0
    if(normal.Mag() == 0.) {
	Error("setPlane()", "Normal vector of plane has length zero.");
        return kFALSE;
    }
#endif
    vCenter = origin;
    vNormal = normal.Unit();
    
    if(vCenter * vNormal < 0.) {
        vNormal *= -1.;
    }
    
    if(vNormal.X() != 0. && vNormal.Y() != 0.) {
	vAxisU.SetXYZ(-vNormal.Y(), vNormal.X(), 0.);
        vAxisU.SetMag(1.);
    } else {
	vAxisU.SetXYZ(1., 0., 0.); 
    }
    vAxisV  = vNormal.Cross(vAxisU);
    vAxisV.SetMag(1.);
    return kTRUE;
}
Bool_t HKalPlane::setPlane(const TVector3 &origin, const TVector3 &u, const TVector3 &v) {
    
    
    Bool_t axisOrth = kTRUE;
    if(TMath::Abs(u * v) > 1.e-3) {
#if kalDebug > 0
	Double_t angle = u.Angle(v) * TMath::RadToDeg();
	Warning("setPlane()",
		Form("The plane's axis u and v are not orthogonal. The Angle between them is %f degrees.", angle));
#endif
        axisOrth = kFALSE;
    }
    vCenter = origin;
    vAxisU  = u.Unit();
    vAxisV  = v.Unit();
    vNormal = u.Cross(v);
    vNormal = vNormal.Unit();
    
    if(vCenter * vNormal < 0.) {
        vNormal *= -1.;
    }
    return axisOrth;
}