/* Copyright 2008-2010, Technische Universitaet Muenchen,
Authors: Christian Hoeppner & Sebastian Neubert
This file is part of GENFIT.
GENFIT is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
GENFIT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with GENFIT. If not, see .
*/
#include "GFDetPlane.h"
#include "assert.h"
#include
#include
#include "TMath.h"
#include "TRandom3.h"
ClassImp(GFDetPlane)
GFDetPlane::GFDetPlane(const TVector3& o,
const TVector3& u,
const TVector3& v,
GFAbsFinitePlane* finite)
:fO(o),fU(u),fV(v),fFinitePlane(finite)
{
sane();
}
GFDetPlane::GFDetPlane(GFAbsFinitePlane* finite)
:fFinitePlane(finite)
{
static TRandom3 r(0);
fO.SetXYZ(0.,0.,0.);
fU.SetXYZ(r.Uniform(),r.Uniform(),0.);
fV.SetXYZ(r.Uniform(),r.Uniform(),0.);
sane();
}
GFDetPlane::GFDetPlane(const TVector3& o,
const TVector3& n,
GFAbsFinitePlane* finite)
:fO(o),fFinitePlane(finite){
setNormal(n);
}
GFDetPlane::~GFDetPlane(){
if(fFinitePlane!=NULL) delete fFinitePlane;
}
GFDetPlane::GFDetPlane(const GFDetPlane& rhs) : TObject(rhs) {
if(rhs.fFinitePlane != NULL) fFinitePlane = rhs.fFinitePlane->clone();
else fFinitePlane = NULL;
fO = rhs.fO;
fU = rhs.fU;
fV = rhs.fV;
}
GFDetPlane& GFDetPlane::operator=(const GFDetPlane& rhs){
assert(this!=&rhs);
if(fFinitePlane!=NULL) {
delete fFinitePlane;
}
if(rhs.fFinitePlane != NULL){
fFinitePlane = rhs.fFinitePlane->clone();
}
else{
fFinitePlane = NULL;
}
fO = rhs.fO;
fU = rhs.fU;
fV = rhs.fV;
return *this;
}
void
GFDetPlane::set(const TVector3& o,
const TVector3& u,
const TVector3& v)
{
fO=o;fU=u;fV=v;
sane();
}
void
GFDetPlane::setO(const TVector3& o)
{
fO=o;
sane();
}
void
GFDetPlane::setO(double X,double Y,double Z)
{
fO.SetXYZ(X,Y,Z);
sane();
}
void
GFDetPlane::setU(const TVector3& u)
{
fU=u;
sane();
}
void
GFDetPlane::setU(double X,double Y,double Z)
{
fU.SetXYZ(X,Y,Z);
sane();
}
void
GFDetPlane::setV(const TVector3& v)
{
fV=v;
sane();
}
void
GFDetPlane::setV(double X,double Y,double Z)
{
fV.SetXYZ(X,Y,Z);
sane();
}
void
GFDetPlane::setUV(const TVector3& u,const TVector3& v)
{
fU=u;
fV=v;
sane();
}
TVector3
GFDetPlane::getNormal() const
{
TVector3 result=fU.Cross(fV);
result.SetMag(1.);
return result;
}
void GFDetPlane::setON(const TVector3& o,const TVector3& n){
fO = o;
setNormal(n);
}
void
GFDetPlane::setNormal(double X,double Y,double Z){
TVector3 N(X,Y,Z);
setNormal(N);
}
void
GFDetPlane::setNormal(TVector3 n){
n.SetMag(1.);
if( fabs(n.X()) > 0.1 ){
fU.SetXYZ(1./n.X()*(-1.*n.Y()-1.*n.Z()),1.,1.);
fU.SetMag(1.);
}
else {
if(fabs(n.Y()) > 0.1){
fU.SetXYZ(1.,1./n.Y()*(-1.*n.X()-1.*n.Z()),1.);
fU.SetMag(1.);
}
else{
fU.SetXYZ(1.,1.,1./n.Z()*(-1.*n.X()-1.*n.Y()));
fU.SetMag(1.);
}
}
fV=n.Cross(fU);
}
void GFDetPlane::setNormal(const double& theta, const double& phi){
TVector3 n(TMath::Sin(theta)*TMath::Cos(phi),TMath::Sin(theta)*TMath::Sin(phi),TMath::Cos(theta));
setNormal(n);
}
TVector2
GFDetPlane::project(const TVector3& x)const
{
Double_t xfU=fU*x;
Double_t xfV=fV*x;
return TVector2(xfU,xfV);
}
TVector2
GFDetPlane::LabToPlane(const TVector3& x)const
{
TVector3 d=x-fO;
return project(d);
}
TVector3
GFDetPlane::toLab(const TVector2& x)const
{
TVector3 d(fO);
d+=x.X()*fU;
d+=x.Y()*fV;
return d;
}
TVector3
GFDetPlane::dist(const TVector3& x)const
{
TVector2 p=LabToPlane(x);
TVector3 xplane=toLab(p);
return xplane-x;
}
void
GFDetPlane::sane(){
assert(fU!=fV);
// ensure unit vectors
fU.SetMag(1.);
fV.SetMag(1.);
// ensure orthogonal system
// fV should be reached by
// rotating fU around _n in a counterclockwise direction
TVector3 n=getNormal();
fV=n.Cross(fU);
TVector3 v=fU;
v.Rotate(TMath::Pi()*0.5,n);
TVector3 null=v-fV;
assert(null.Mag()<1E-6);
}
void
GFDetPlane::Print() const
{
std::cout<<"GFDetPlane: "
<<"O("<Print();
}
/*
I could write pages of comments about correct equality checking for
floating point numbers, but: When two planes are as close as 10E-5 cm
in all nine numbers that define the plane, this will be enough for all
practical purposes
*/
#define DETPLANE_EPSILON 1.E-5
bool operator== (const GFDetPlane& lhs, const GFDetPlane& rhs){
if(
fabs( (lhs.fO.X()-rhs.fO.X()) ) > DETPLANE_EPSILON ||
fabs( (lhs.fO.Y()-rhs.fO.Y()) ) > DETPLANE_EPSILON ||
fabs( (lhs.fO.Z()-rhs.fO.Z()) ) > DETPLANE_EPSILON
) return false;
else if(
fabs( (lhs.fU.X()-rhs.fU.X()) ) > DETPLANE_EPSILON ||
fabs( (lhs.fU.Y()-rhs.fU.Y()) ) > DETPLANE_EPSILON ||
fabs( (lhs.fU.Z()-rhs.fU.Z()) ) > DETPLANE_EPSILON
) return false;
else if(
fabs( (lhs.fV.X()-rhs.fV.X()) ) > DETPLANE_EPSILON ||
fabs( (lhs.fV.Y()-rhs.fV.Y()) ) > DETPLANE_EPSILON ||
fabs( (lhs.fV.Z()-rhs.fV.Z()) ) > DETPLANE_EPSILON
) return false;
return true;
}
bool operator!= (const GFDetPlane& lhs, const GFDetPlane& rhs){
return !(lhs==rhs);
}
void GFDetPlane::getGraphics(double mesh, double length, TPolyMarker3D **pl,TPolyLine3D** plLine, TPolyLine3D **u, TPolyLine3D **v, TPolyLine3D**n){
*pl = new TPolyMarker3D(21*21,24);
(*pl)->SetMarkerSize(0.1);
(*pl)->SetMarkerColor(kBlue);
int nI=10;
int nJ=10;
*plLine = new TPolyLine3D(5);
{
TVector3 linevec;
int i,j;
i=-1*nI;j=-1*nJ;
linevec=(fO+(mesh*i)*fU+(mesh*j)*fV);
(*plLine)->SetPoint(0,linevec.X(),linevec.Y(),linevec.Z());
i=-1*nI;j=1*nJ;
linevec=(fO+(mesh*i)*fU+(mesh*j)*fV);
(*plLine)->SetPoint(0,linevec.X(),linevec.Y(),linevec.Z());
i=1*nI;j=-1*nJ;
linevec=(fO+(mesh*i)*fU+(mesh*j)*fV);
(*plLine)->SetPoint(2,linevec.X(),linevec.Y(),linevec.Z());
i=1*nI;j=1*nJ;
linevec=(fO+(mesh*i)*fU+(mesh*j)*fV);
(*plLine)->SetPoint(1,linevec.X(),linevec.Y(),linevec.Z());
i=-1*nI;j=-1*nJ;
linevec=(fO+(mesh*i)*fU+(mesh*j)*fV);
(*plLine)->SetPoint(4,linevec.X(),linevec.Y(),linevec.Z());
}
for (int i=-1*nI;i<=nI;++i){
for (int j=-1*nJ;j<=nJ;++j){
TVector3 vec(fO+(mesh*i)*fU+(mesh*j)*fV);
int id=(i+10)*21+j+10;
(*pl)->SetPoint(id,vec.X(),vec.Y(),vec.Z());
}
}
*u = new TPolyLine3D(2);
(*u)->SetPoint(0,fO.X(),fO.Y(),fO.Z());
(*u)->SetPoint(1,fO.X()+length*fU.X(),fO.Y()+length*fU.Y(),fO.Z()+length*fU.Z());
(*u)->SetLineWidth(2);
(*u)->SetLineColor(kGreen);
*v = new TPolyLine3D(2);
(*v)->SetPoint(0,fO.X(),fO.Y(),fO.Z());
(*v)->SetPoint(1,fO.X()+length*fV.X(),fO.Y()+length*fV.Y(),fO.Z()+length*fV.Z());
(*v)->SetLineWidth(2);
(*v)->SetLineColor(kRed);
if(n!=NULL){
*n = new TPolyLine3D(2);
TVector3 _n=getNormal();
(*n)->SetPoint(0,fO.X(),fO.Y(),fO.Z());
(*n)->SetPoint(1,fO.X()+length*_n.X(),fO.Y()+length*_n.Y(),fO.Z()+length*_n.Z());
(*n)->SetLineWidth(2);
(*n)->SetLineColor(kBlue);
}
}
double GFDetPlane::distance(TVector3& v) const{
double s = (v - fO)*fU;
double t = (v - fO)*fV;
TVector3 distanceVector = v - fO - (s*fU) - (t*fV);
return distanceVector.Mag();
}
double GFDetPlane::distance(double x,double y,double z) const{
TVector3 v(x,y,z);
double s = (v - fO)*fU;
double t = (v - fO)*fV;
TVector3 distanceVector = v - fO - (s*fU) - (t*fV);
return distanceVector.Mag();
}
TVector2 GFDetPlane::straightLineToPlane (const TVector3& point,const TVector3& dir) const{
TVector3 dirNorm(dir);
dirNorm.SetMag(1.);
TVector3 normal = getNormal();
double dirTimesN = dirNorm*normal;
if(fabs(dirTimesN)<1.E-6){//straight line is parallel to plane, so return infinity
//doesnt parallel mean that they cross in infinity ;-)
return TVector2(1.E100,1.E100);
}
double t = 1/dirTimesN * ((fO-point)*normal);
return project(point - fO + t * dirNorm);
}