Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
REveProjections.cxx
Go to the documentation of this file.
1 // @(#)root/eve7:$Id$
2 // Authors: Matevz Tadel & Alja Mrak-Tadel: 2006, 2007
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2019, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 #include "TError.h"
13 
14 #include <ROOT/REveProjections.hxx>
15 #include <ROOT/REveTrans.hxx>
16 #include <ROOT/REveUtil.hxx>
17 
18 #include <limits>
19 
20 using namespace ROOT::Experimental;
21 namespace REX = ROOT::Experimental;
22 
23 /** \class REveProjection
24 \ingroup REve
25 Base-class for non-linear projections.
26 
27 Enables to define an external center of distortion and a scale to
28 fixate a bounding box of a projected point.
29 */
30 
31 Float_t REX::REveProjection::fgEps = 0.005f;
32 Float_t REX::REveProjection::fgEpsSqr = 0.000025f;
33 
34 ////////////////////////////////////////////////////////////////////////////////
35 /// Constructor.
36 
37 REveProjection::REveProjection() :
38  fType (kPT_Unknown),
39  fGeoMode (kGM_Unknown),
40  fName (),
41  fCenter (),
42  fDisplaceOrigin (kFALSE),
43  fUsePreScale (kFALSE),
44  fDistortion (0.0f),
45  fFixR (300), fFixZ (400),
46  fPastFixRFac (0), fPastFixZFac (0),
47  fScaleR (1), fScaleZ (1),
48  fPastFixRScale (1), fPastFixZScale (1),
49  fMaxTrackStep (25) // XXXXX This is STOOPID ... see also comment in REveTrackProjected::MakeTrack()
50 {
51 }
52 
53 ////////////////////////////////////////////////////////////////////////////////
54 /// Project float array.
55 
56 void REveProjection::ProjectPointfv(Float_t* v, Float_t d)
57 {
58  ProjectPoint(v[0], v[1], v[2], d);
59 }
60 
61 ////////////////////////////////////////////////////////////////////////////////
62 /// Project double array.
63 /// This is a bit piggish as we convert the doubles to floats and back.
64 
65 void REveProjection::ProjectPointdv(Double_t* v, Float_t d)
66 {
67  Float_t x = v[0], y = v[1], z = v[2];
68  ProjectPoint(x, y, z, d);
69  v[0] = x; v[1] = y; v[2] = z;
70 }
71 
72 ////////////////////////////////////////////////////////////////////////////////
73 /// Project REveVector.
74 
75 void REveProjection::ProjectVector(REveVector& v, Float_t d)
76 {
77  ProjectPoint(v.fX, v.fY, v.fZ, d);
78 }
79 
80 ////////////////////////////////////////////////////////////////////////////////
81 /// Project float array, converting it to global coordinate system first if
82 /// transformation matrix is set.
83 
84 void REveProjection::ProjectPointfv(const REveTrans* t, const Float_t* p, Float_t* v, Float_t d)
85 {
86  v[0] = p[0]; v[1] = p[1]; v[2] = p[2];
87  if (t)
88  {
89  t->MultiplyIP(v);
90  }
91  ProjectPoint(v[0], v[1], v[2], d);
92 }
93 
94 ////////////////////////////////////////////////////////////////////////////////
95 /// Project double array, converting it to global coordinate system first if
96 /// transformation matrix is set.
97 /// This is a bit piggish as we convert the doubles to floats and back.
98 
99 void REveProjection::ProjectPointdv(const REveTrans* t, const Double_t* p, Double_t* v, Float_t d)
100 {
101  Float_t x, y, z;
102  if (t)
103  {
104  t->Multiply(p, v);
105  x = v[0]; y = v[1]; z = v[2];
106  }
107  else
108  {
109  x = p[0]; y = p[1]; z = p[2];
110  }
111  ProjectPoint(x, y, z, d);
112  v[0] = x; v[1] = y; v[2] = z;
113 }
114 
115 ////////////////////////////////////////////////////////////////////////////////
116 /// Project REveVector, converting it to global coordinate system first if
117 /// transformation matrix is set.
118 
119 void REveProjection::ProjectVector(const REveTrans* t, REveVector& v, Float_t d)
120 {
121  if (t)
122  {
123  t->MultiplyIP(v);
124  }
125  ProjectPoint(v.fX, v.fY, v.fZ, d);
126 }
127 
128 ////////////////////////////////////////////////////////////////////////////////
129 /// Pre-scale single variable with pre-scale entry dim.
130 
131 void REveProjection::PreScaleVariable(Int_t dim, Float_t& v)
132 {
133  if (!fPreScales[dim].empty())
134  {
135  Bool_t invp = kFALSE;
136  if (v < 0) {
137  v = -v;
138  invp = kTRUE;
139  }
140  auto i = fPreScales[dim].begin();
141  while (v > i->fMax)
142  ++i;
143  v = i->fOffset + (v - i->fMin)*i->fScale;
144  if (invp)
145  v = -v;
146  }
147 }
148 
149 ////////////////////////////////////////////////////////////////////////////////
150 /// Pre-scale point (x, y) in projected coordinates for 2D projections:
151 /// - RhoZ ~ (rho, z)
152 /// - RPhi ~ (r, phi), scaling phi doesn't make much sense.
153 
154 void REveProjection::PreScalePoint(Float_t& x, Float_t& y)
155 {
156  PreScaleVariable(0, x);
157  PreScaleVariable(1, y);
158 }
159 
160 ////////////////////////////////////////////////////////////////////////////////
161 /// Pre-scale point (x, y, z) in projected coordinates for 3D projection.
162 
163 void REveProjection::PreScalePoint(Float_t& x, Float_t& y, Float_t& z)
164 {
165  PreScaleVariable(0, x);
166  PreScaleVariable(1, y);
167  PreScaleVariable(2, z);
168 }
169 
170 ////////////////////////////////////////////////////////////////////////////////
171 /// Add new scaling range for given coordinate.
172 /// Arguments:
173 /// - coord 0 ~ x, 1 ~ y, 2 ~ z
174 /// - value value of input coordinate from which to apply this scale;
175 /// - scale the scale to apply from value onwards.
176 ///
177 /// NOTE: If pre-scaling is combined with center-displaced then
178 /// the scale of the central region should be 1. This limitation
179 /// can be removed but will cost CPU.
180 
181 void REveProjection::AddPreScaleEntry(Int_t coord, Float_t value, Float_t scale)
182 {
183  static const REveException eh("REveProjection::AddPreScaleEntry ");
184 
185  if (coord < 0 || coord > 2)
186  throw (eh + "coordinate out of range.");
187 
188  const Float_t infty = std::numeric_limits<Float_t>::infinity();
189 
190  vPreScale_t& vec = fPreScales[coord];
191 
192  if (vec.empty())
193  {
194  if (value == 0)
195  {
196  vec.emplace_back(0, infty, 0, scale);
197  }
198  else
199  {
200  vec.emplace_back(0, value, 0, 1);
201  vec.emplace_back(value, infty, value, scale);
202  }
203  }
204  else
205  {
206  PreScaleEntry_t& prev = vec.back();
207  if (value <= prev.fMin)
208  throw (eh + "minimum value not larger than previous one.");
209 
210  prev.fMax = value;
211  Float_t offset = prev.fOffset + (prev.fMax - prev.fMin)*prev.fScale;
212  vec.emplace_back(value, infty, offset, scale);
213  }
214 }
215 
216 ////////////////////////////////////////////////////////////////////////////////
217 /// Change scale for given entry and coordinate.
218 ///
219 /// NOTE: If the first entry you created used other value than 0,
220 /// one entry (covering range from 0 to this value) was created
221 /// automatically.
222 
223 void REveProjection::ChangePreScaleEntry(Int_t coord, Int_t entry,
224  Float_t new_scale)
225 {
226  static const REveException eh("REveProjection::ChangePreScaleEntry ");
227 
228  if (coord < 0 || coord > 2)
229  throw (eh + "coordinate out of range.");
230 
231  vPreScale_t& vec = fPreScales[coord];
232  Int_t vs = vec.size();
233  if (entry < 0 || entry >= vs)
234  throw (eh + "entry out of range.");
235 
236  vec[entry].fScale = new_scale;
237  Int_t i0 = entry, i1 = entry + 1;
238  while (i1 < vs)
239  {
240  PreScaleEntry_t e0 = vec[i0];
241  vec[i1].fOffset = e0.fOffset + (e0.fMax - e0.fMin)*e0.fScale;
242  i0 = i1++;
243  }
244 }
245 
246 ////////////////////////////////////////////////////////////////////////////////
247 /// Clear all pre-scaling information.
248 
249 void REveProjection::ClearPreScales()
250 {
251  fPreScales[0].clear();
252  fPreScales[1].clear();
253  fPreScales[2].clear();
254 }
255 
256 ////////////////////////////////////////////////////////////////////////////////
257 /// Set distortion.
258 
259 void REveProjection::SetDistortion(Float_t d)
260 {
261  fDistortion = d;
262  fScaleR = 1.0f + fFixR*fDistortion;
263  fScaleZ = 1.0f + fFixZ*fDistortion;
264  fPastFixRScale = TMath::Power(10.0f, fPastFixRFac) / fScaleR;
265  fPastFixZScale = TMath::Power(10.0f, fPastFixZFac) / fScaleZ;
266 }
267 
268 ////////////////////////////////////////////////////////////////////////////////
269 /// Set fixed radius.
270 
271 void REveProjection::SetFixR(Float_t r)
272 {
273  fFixR = r;
274  fScaleR = 1 + fFixR*fDistortion;
275  fPastFixRScale = TMath::Power(10.0f, fPastFixRFac) / fScaleR;
276 }
277 
278 ////////////////////////////////////////////////////////////////////////////////
279 /// Set fixed radius.
280 
281 void REveProjection::SetFixZ(Float_t z)
282 {
283  fFixZ = z;
284  fScaleZ = 1 + fFixZ*fDistortion;
285  fPastFixZScale = TMath::Power(10.0f, fPastFixZFac) / fScaleZ;
286 }
287 
288 ////////////////////////////////////////////////////////////////////////////////
289 /// Set 2's-exponent for relative scaling beyond FixR.
290 
291 void REveProjection::SetPastFixRFac(Float_t x)
292 {
293  fPastFixRFac = x;
294  fPastFixRScale = TMath::Power(10.0f, fPastFixRFac) / fScaleR;
295 }
296 
297 ////////////////////////////////////////////////////////////////////////////////
298 /// Get projected center.
299 
300 Float_t* REveProjection::GetProjectedCenter()
301 {
302  static REveVector zero;
303 
304  if (fDisplaceOrigin)
305  return zero.Arr();
306  else
307  return fCenter.Arr();
308 }
309 
310 ////////////////////////////////////////////////////////////////////////////////
311 /// Set flag to displace for center.
312 /// This options is useful if want to have projected center
313 /// at (0, 0) position in projected coordinates and want to dismiss
314 /// gap around projected center in RhoZ projection.
315 
316 void REveProjection::SetDisplaceOrigin(Bool_t x)
317 {
318  fDisplaceOrigin = x;
319  // update projected center
320  SetCenter(fCenter);
321 }
322 
323 ////////////////////////////////////////////////////////////////////////////////
324 /// Set 2's-exponent for relative scaling beyond FixZ.
325 
326 void REveProjection::SetPastFixZFac(Float_t x)
327 {
328  fPastFixZFac = x;
329  fPastFixZScale = TMath::Power(10.0f, fPastFixZFac) / fScaleZ;
330 }
331 
332 ////////////////////////////////////////////////////////////////////////////////
333 /// Find break-point on both sides of the discontinuity.
334 /// They still need to be projected after the call.
335 /// This is an obsolete version of the method that required manual
336 /// specification of precision -- this lead to (infrequent) infinite loops.
337 
338 void REveProjection::BisectBreakPoint(REveVector& vL, REveVector& vR, Float_t /*eps_sqr*/)
339 {
340  static Bool_t warnedp = kFALSE;
341 
342  if (!warnedp)
343  {
344  Warning("BisectBreakPoint", "call with eps_sqr argument is obsolete - please use the new signature.");
345  warnedp = kTRUE;
346  }
347 
348  BisectBreakPoint(vL, vR, kFALSE);
349 }
350 
351 ////////////////////////////////////////////////////////////////////////////////
352 /// Find break-point on both sides of the discontinuity.
353 /// If project_result is true, the resulting break points will be projected
354 /// with given depth value.
355 
356 void REveProjection::BisectBreakPoint(REveVector& vL, REveVector& vR,
357  Bool_t project_result, Float_t depth)
358 {
359  REveVector vM, vLP, vMP;
360  Int_t n_loops = TMath::CeilNint(TMath::Log2(1e12 * (vL-vR).Mag2() / (0.5f*(vL+vR)).Mag2()) / 2);
361  while (--n_loops >= 0)
362  {
363  vM.Mult(vL + vR, 0.5f);
364  vLP.Set(vL); ProjectPoint(vLP.fX, vLP.fY, vLP.fZ, 0);
365  vMP.Set(vM); ProjectPoint(vMP.fX, vMP.fY, vMP.fZ, 0);
366 
367  if (IsOnSubSpaceBoundrary(vMP))
368  {
369  vL.Set(vM);
370  vR.Set(vM);
371  break;
372  }
373 
374  if (AcceptSegment(vLP, vMP, 0.0f))
375  {
376  vL.Set(vM);
377  }
378  else
379  {
380  vR.Set(vM);
381  }
382  }
383 
384  if (project_result)
385  {
386  ProjectVector(vL, depth);
387  ProjectVector(vR, depth);
388  }
389 }
390 
391 ////////////////////////////////////////////////////////////////////////////////
392 /// Get vector for axis in a projected space.
393 
394 void REveProjection::SetDirectionalVector(Int_t screenAxis, REveVector& vec)
395 {
396  for (Int_t i=0; i<3; i++)
397  {
398  vec[i] = (i==screenAxis) ? 1.0f : 0.0f;
399  }
400 }
401 
402 ////////////////////////////////////////////////////////////////////////////////
403 /// Get center ortogonal to given axis index.
404 
405 REveVector REveProjection::GetOrthogonalCenter(int i, REveVector& centerOO)
406 {
407  REveVector dirVec;
408  SetDirectionalVector(i, dirVec);
409 
410  REveVector dirCenter;
411  dirCenter.Mult(dirVec, fCenter.Dot(dirVec));
412  centerOO = fCenter - dirCenter;
413 
414 
415  return centerOO;
416 }
417 
418 ////////////////////////////////////////////////////////////////////////////////
419 /// Inverse projection.
420 
421 Float_t REveProjection::GetValForScreenPos(Int_t axisIdx, Float_t sv)
422 {
423  static const REveException eH("REveProjection::GetValForScreenPos ");
424 
425  static const int kMaxSteps = 5000;
426  static const int kMaxVal = 10;
427 
428  Float_t xL, xM, xR;
429  REveVector vec;
430 
431  REveVector dirVec;
432  SetDirectionalVector(axisIdx, dirVec);
433 
434  REveVector zero;
435  if (fDisplaceOrigin) zero = fCenter;
436 
437  REveVector zeroProjected = zero;
438  ProjectVector(zeroProjected, 0.f);
439 
440  // search from -/+ infinity according to sign of screen value
441  if (sv > zeroProjected[axisIdx])
442  {
443  xL = 0;
444  xR = kMaxVal;
445 
446  int cnt = 0;
447  while (cnt < kMaxSteps)
448  {
449  vec.Mult(dirVec, xR);
450  if (fDisplaceOrigin) vec += fCenter;
451 
452  ProjectVector(vec, 0);
453  if (vec[axisIdx] >= sv) break;
454  xL = xR; xR *= 2;
455 
456  if (++cnt >= kMaxSteps)
457  throw eH + Form("positive projected %f, value %f,xL, xR ( %f, %f)\n", vec[axisIdx], sv, xL, xR);
458  }
459  }
460  else if (sv < zeroProjected[axisIdx])
461  {
462  xR = 0;
463  xL = -kMaxVal;
464 
465  int cnt = 0;
466  while (cnt < kMaxSteps)
467  {
468  vec.Mult(dirVec, xL);
469  if (fDisplaceOrigin) vec += fCenter;
470 
471  ProjectVector(vec, 0);
472  if (vec[axisIdx] <= sv) break;
473  xR = xL; xL *= 2;
474  if (++cnt >= kMaxSteps)
475  throw eH + Form("negative projected %f, value %f,xL, xR ( %f, %f)\n", vec[axisIdx], sv, xL, xR);
476  }
477  }
478  else
479  {
480  return 0.0f;
481  }
482 
483  // printf("search for value %f in rng[%f, %f] \n", sv, xL, xR);
484  int cnt = 0;
485  do
486  {
487  //printf("search value with bisection xL=%f, xR=%f; vec[axisIdx]=%f, sv=%f\n", xL, xR, vec[axisIdx], sv);
488  xM = 0.5f * (xL + xR);
489  vec.Mult(dirVec, xM);
490  if (fDisplaceOrigin) vec += fCenter;
491  ProjectVector(vec, 0);
492  if (vec[axisIdx] > sv)
493  xR = xM;
494  else
495  xL = xM;
496  if (++cnt >= kMaxSteps)
497  throw eH + Form("can't converge %f %f, l/r %f/%f, idx=%d\n", vec[axisIdx], sv, xL, xR, axisIdx);
498 
499  } while (TMath::Abs(vec[axisIdx] - sv) >= fgEps);
500 
501 
502  return xM;
503 }
504 
505 ////////////////////////////////////////////////////////////////////////////////
506 /// Project point on given axis and return projected value.
507 
508 Float_t REveProjection::GetScreenVal(Int_t i, Float_t x, REveVector& dirVec, REveVector& /*oCenter*/)
509 {
510  REveVector pos = dirVec*x;
511 
512  if (fDisplaceOrigin)
513  pos += fCenter;
514 
515  ProjectVector(pos , 0.f);
516 
517  return pos[i];
518 }
519 
520 ////////////////////////////////////////////////////////////////////////////////
521 /// Project point on given axis and return projected value.
522 
523 Float_t REveProjection::GetScreenVal(Int_t i, Float_t x)
524 {
525  REveVector dirVec;
526  SetDirectionalVector(i, dirVec);
527  REveVector oCenter;
528  // GetOrthogonalCenter(i, oCenter);
529  return GetScreenVal(i, x, dirVec, oCenter);
530 }
531 
532 /** \class REveRhoZProjection
533 \ingroup REve
534 Transformation from 3D to 2D. X axis represent Z coordinate. Y axis have value of
535 radius with a sign of Y coordinate.
536 */
537 
538 ////////////////////////////////////////////////////////////////////////////////
539 /// Constructor.
540 
541 REveRhoZProjection::REveRhoZProjection() :
542  REveProjection()
543 {
544  fType = kPT_RhoZ;
545  fName = "RhoZ";
546 }
547 
548 ////////////////////////////////////////////////////////////////////////////////
549 /// Project point.
550 
551 void REveRhoZProjection::ProjectPoint(Float_t& x, Float_t& y, Float_t& z,
552  Float_t d, EPProc_e proc)
553 {
554  using namespace TMath;
555 
556  if (fDisplaceOrigin) {
557  x -= fCenter.fX;
558  y -= fCenter.fY;
559  z -= fCenter.fZ;
560  }
561  if (proc == kPP_Plane || proc == kPP_Full)
562  {
563  // project
564  y = Sign((Float_t)Sqrt(x*x+y*y), y);
565  x = z;
566  }
567  if (proc == kPP_Distort || proc == kPP_Full)
568  {
569  if (fUsePreScale)
570  PreScalePoint(y, x);
571 
572 
573  // distort
574 
575  if (!fDisplaceOrigin) {
576  x -= fProjectedCenter.fX;
577  y -= fProjectedCenter.fY;
578  }
579 
580  if (x > fFixZ)
581  x = fFixZ + fPastFixZScale*(x - fFixZ);
582  else if (x < -fFixZ)
583  x = -fFixZ + fPastFixZScale*(x + fFixZ);
584  else
585  x = x * fScaleZ / (1.0f + Abs(x)*fDistortion);
586 
587  if (y > fFixR)
588  y = fFixR + fPastFixRScale*(y - fFixR);
589  else if (y < -fFixR)
590  y = -fFixR + fPastFixRScale*(y + fFixR);
591  else
592  y = y * fScaleR / (1.0f + Abs(y)*fDistortion);
593 
594  if (!fDisplaceOrigin) {
595  x += fProjectedCenter.fX;
596  y += fProjectedCenter.fY;
597  }
598  }
599  z = d;
600 }
601 
602 ////////////////////////////////////////////////////////////////////////////////
603 /// Set center of distortion (virtual method).
604 
605 void REveRhoZProjection::SetCenter(REveVector& v)
606 {
607  fCenter = v;
608 
609  if (fDisplaceOrigin)
610  {
611  fProjectedCenter.Set(0.f, 0.f, 0.f);
612  }
613  else
614  {
615  Float_t r = TMath::Sqrt(v.fX*v.fX + v.fY*v.fY);
616  fProjectedCenter.fX = fCenter.fZ;
617  fProjectedCenter.fY = TMath::Sign(r, fCenter.fY);
618  fProjectedCenter.fZ = 0;
619  }
620 }
621 
622 ////////////////////////////////////////////////////////////////////////////////
623 /// Get direction in the unprojected space for axis index in the
624 /// projected space.
625 /// This is virtual method from base-class REveProjection.
626 
627 void REveRhoZProjection::SetDirectionalVector(Int_t screenAxis, REveVector& vec)
628 {
629  if (screenAxis == 0)
630  vec.Set(0.0f, 0.0f, 1.0f);
631  else if (screenAxis == 1)
632  vec.Set(0.0f, 1.0f, 0.0f);
633 
634 }
635 
636 ////////////////////////////////////////////////////////////////////////////////
637 /// Check if segment of two projected points is valid.
638 ///
639 /// Move slightly one of the points if by shifting it by no more than
640 /// tolerance the segment can become acceptable.
641 
642 Bool_t REveRhoZProjection::AcceptSegment(REveVector& v1, REveVector& v2,
643  Float_t tolerance) const
644 {
645  Float_t a = fProjectedCenter.fY;
646  Bool_t val = kTRUE;
647  if ((v1.fY < a && v2.fY > a) || (v1.fY > a && v2.fY < a))
648  {
649  val = kFALSE;
650  if (tolerance > 0)
651  {
652  Float_t a1 = TMath::Abs(v1.fY - a), a2 = TMath::Abs(v2.fY - a);
653  if (a1 < a2)
654  {
655  if (a1 < tolerance) { v1.fY = a; val = kTRUE; }
656  }
657  else
658  {
659  if (a2 < tolerance) { v2.fY = a; val = kTRUE; }
660  }
661  }
662  }
663  return val;
664 }
665 
666 ////////////////////////////////////////////////////////////////////////////////
667 /// Return sub-space id for the point.
668 /// 0 - upper half-space
669 /// 1 - lower half-space
670 
671 Int_t REveRhoZProjection::SubSpaceId(const REveVector& v) const
672 {
673  return v.fY > fProjectedCenter.fY ? 0 : 1;
674 }
675 
676 ////////////////////////////////////////////////////////////////////////////////
677 /// Checks if point is on sub-space boundary.
678 
679 Bool_t REveRhoZProjection::IsOnSubSpaceBoundrary(const REveVector& v) const
680 {
681  return v.fY == fProjectedCenter.fY;
682 }
683 
684 /** \class REveRPhiProjection
685 \ingroup REve
686 XY projection with distortion around given center.
687 */
688 
689 ////////////////////////////////////////////////////////////////////////////////
690 /// Constructor.
691 
692 REveRPhiProjection::REveRPhiProjection() :
693  REveProjection()
694 {
695  fType = kPT_RPhi;
696  fGeoMode = kGM_Polygons;
697  fName = "RhoPhi";
698 }
699 
700 ////////////////////////////////////////////////////////////////////////////////
701 /// Project point.
702 
703 void REveRPhiProjection::ProjectPoint(Float_t& x, Float_t& y, Float_t& z,
704  Float_t d, EPProc_e proc)
705 {
706  using namespace TMath;
707 
708  if (fDisplaceOrigin)
709  {
710  x -= fCenter.fX;
711  y -= fCenter.fY;
712  z -= fCenter.fZ;
713  }
714 
715  if (proc != kPP_Plane)
716  {
717  Float_t r, phi;
718  if (fUsePreScale)
719  {
720  r = Sqrt(x*x + y*y);
721  phi = (x == 0.0f && y == 0.0f) ? 0.0f : ATan2(y, x);
722  PreScalePoint(r, phi);
723  x = r*Cos(phi);
724  y = r*Sin(phi);
725  }
726 
727  if (!fDisplaceOrigin)
728  {
729  x -= fCenter.fX;
730  y -= fCenter.fY;
731  }
732 
733  r = Sqrt(x*x + y*y);
734  phi = (x == 0.0f && y == 0.0f) ? 0.0f : ATan2(y, x);
735 
736  if (r > fFixR)
737  r = fFixR + fPastFixRScale*(r - fFixR);
738  else if (r < -fFixR)
739  r = -fFixR + fPastFixRScale*(r + fFixR);
740  else
741  r = r * fScaleR / (1.0f + r*fDistortion);
742 
743  x = r*Cos(phi);
744  y = r*Sin(phi);
745 
746  if (!fDisplaceOrigin)
747  {
748  x += fCenter.fX;
749  y += fCenter.fY;
750  }
751  }
752  z = d;
753 }
754 
755 /** \class REve3DProjection
756 \ingroup REve
757 3D scaling projection. One has to use pre-scaling to make any ise of this.
758 */
759 
760 ////////////////////////////////////////////////////////////////////////////////
761 /// Constructor.
762 
763 REve3DProjection::REve3DProjection() :
764  REveProjection()
765 {
766  fType = kPT_3D;
767  fGeoMode = kGM_Unknown;
768  fName = "3D";
769 }
770 
771 ////////////////////////////////////////////////////////////////////////////////
772 /// Project point.
773 
774 void REve3DProjection::ProjectPoint(Float_t& x, Float_t& y, Float_t& z,
775  Float_t /*d*/, EPProc_e proc)
776 {
777  using namespace TMath;
778 
779  if (proc != kPP_Plane)
780  {
781  if (fUsePreScale)
782  {
783  PreScalePoint(x, y, z);
784  }
785 
786  x -= fCenter.fX;
787  y -= fCenter.fY;
788  z -= fCenter.fZ;
789  }
790 }