1 #include "NLTProjections.h"
7 //______________________________________________________________________________
10 // Base-class for non-linear projection of 3D point.
11 // Enables to define an external center of distortion and a scale to
12 // fixate a bounding box of a projected point.
14 ClassImp(Reve::NLTProjection)
16 Float_t NLTProjection::fgEps = 0.005f;
17 //______________________________________________________________________________
18 NLTProjection::NLTProjection(Vector& center) :
22 fCenter(center.x, center.y, center.z),
30 //______________________________________________________________________________
31 void NLTProjection::ProjectVector(Vector& v)
33 // Project Reve::Vector.
35 ProjectPoint(v.x, v.y, v.z);
38 //______________________________________________________________________________
39 void NLTProjection::UpdateLimit()
41 // Update convergence in +inf and -inf.
43 if ( fDistortion == 0.0f )
46 Float_t lim = 1.0f/fDistortion + fFixedRadius;
47 Float_t* c = GetProjectedCenter();
48 fUpLimit.Set(lim + c[0], lim + c[1], c[2]);
49 fLowLimit.Set(-lim + c[0], -lim + c[1], c[2]);
52 //______________________________________________________________________________
53 void NLTProjection::SetDistortion(Float_t d)
58 fScale = 1+fFixedRadius*fDistortion;
62 //______________________________________________________________________________
63 void NLTProjection::SetFixedRadius(Float_t r)
68 fScale = 1 + fFixedRadius*fDistortion;
72 //______________________________________________________________________________
73 void NLTProjection::SetDirectionalVector(Int_t screenAxis, Vector& vec)
75 // Get vector for axis in a projected space.
77 for (Int_t i=0; i<3; i++)
79 vec[i] = (i==screenAxis) ? 1. : 0.;
83 //______________________________________________________________________________
84 Float_t NLTProjection::GetValForScreenPos(Int_t i, Float_t sv)
86 // Inverse projection.
88 static const Exc_t eH("NLTProjection::GetValForScreenPos ");
92 SetDirectionalVector(i, DirVec);
93 if (fDistortion > 0.0f && ((sv > 0 && sv > fUpLimit[i]) || (sv < 0 && sv < fLowLimit[i])))
94 throw(eH + Form("screen value '%f' out of limit '%f'.", sv, sv > 0 ? fUpLimit[i] : fLowLimit[i]));
96 Vector zero; ProjectVector(zero);
97 // search from -/+ infinity according to sign of screen value
103 V.Mult(DirVec, xR); ProjectVector(V);
104 // printf("positive projected %f, value %f,xL, xR ( %f, %f)\n", V[i], sv, xL, xR);
105 if (V[i] > sv || V[i] == sv) break;
109 else if (sv < zero[i])
114 V.Mult(DirVec, xL); ProjectVector(V);
115 // printf("negative projected %f, value %f,xL, xR ( %f, %f)\n", V[i], sv, xL, xR);
116 if (V[i] < sv || V[i] == sv) break;
127 xM = 0.5f * (xL + xR);
134 } while(TMath::Abs(V[i] - sv) >= fgEps);
139 //______________________________________________________________________________
140 Float_t NLTProjection::GetScreenVal(Int_t i, Float_t x)
142 // Project point on given axis and return projected value.
145 SetDirectionalVector(i, dv); dv = dv*x;
151 //______________________________________________________________________________
154 // Transformation from 3D to 2D. X axis represent Z coordinate. Y axis have value of
155 // radius with a sign of Y coordinate.
157 ClassImp(Reve::NLTRhoZ)
159 //______________________________________________________________________________
160 void NLTRhoZ::SetCenter(Vector& v)
162 // Set center of distortion (virtual method).
166 Float_t R = TMath::Sqrt(v.x*v.x+v.y*v.y);
167 fProjectedCenter.x = fCenter.z;
168 fProjectedCenter.y = TMath::Sign(R, fCenter.y);
169 fProjectedCenter.z = 0;
173 //______________________________________________________________________________
174 void NLTRhoZ::ProjectPoint(Float_t& x, Float_t& y, Float_t& z, PProc_e proc )
178 using namespace TMath;
180 if(proc == PP_Plane || proc == PP_Full)
183 y = Sign((Float_t)Sqrt(x*x+y*y), y);
186 if(proc == PP_Distort || proc == PP_Full)
189 x -= fProjectedCenter.x;
190 y -= fProjectedCenter.y;
192 y = (y*fScale) / (1.0f + Abs(y)*fDistortion);
193 x = (x*fScale) / (1.0f + Abs(x)*fDistortion);
194 // move back from center
195 x += fProjectedCenter.x;
196 y += fProjectedCenter.y;
201 //______________________________________________________________________________
202 void NLTRhoZ::SetDirectionalVector(Int_t screenAxis, Vector& vec)
204 // Get direction in the unprojected space for axis index in the projected space.
205 // This is virtual method from base-class NLTProjection.
209 else if (screenAxis == 1)
213 //______________________________________________________________________________
214 Bool_t NLTRhoZ::AcceptSegment(Vector& v1, Vector& v2, Float_t tolerance)
216 // Check if segment of two projected points is valid.
218 Float_t a = fProjectedCenter.y;
220 if((v1.y < a && v2.y > a) || (v1.y > a && v2.y < a))
225 Float_t a1 = TMath::Abs(v1.y - a), a2 = TMath::Abs(v2.y - a);
228 if (a1 < tolerance) { v1.y = a; val = kTRUE; }
232 if (a2 < tolerance) { v2.y = a; val = kTRUE; }
240 //______________________________________________________________________________
241 // NLTCircularFishEye
243 // XY projection with distortion around given center.
245 ClassImp(Reve::NLTCircularFishEye)
247 //______________________________________________________________________________
248 void NLTCircularFishEye::ProjectPoint(Float_t& x, Float_t& y, Float_t& z,
253 using namespace TMath;
255 if (proc != PP_Plane)
259 Float_t phi = x == 0.0 && y == 0.0 ? 0.0 : ATan2(y,x);
260 Float_t R = Sqrt(x*x+y*y);
262 Float_t NR = (R*fScale) / (1.0f + R*fDistortion);
263 x = NR*Cos(phi) + fCenter.x;
264 y = NR*Sin(phi) + fCenter.y;