LArSoft  v07_13_02
Liquid Argon Software toolkit - http://larsoft.org/
BezierCurveHelper.cxx
Go to the documentation of this file.
1 
11 #include <algorithm>
12 #include <cmath>
13 #include <iostream>
14 #include <map>
15 #include <sstream>
16 
19 
22 #include "cetlib_except/exception.h"
24 
25 #include "TVector.h"
26 
27 
28 namespace trkf{
29 //----------------------------------------------------------------------
30 // Constructor.
31 //
33 {
34  fCurveResolution=100;
35 }
36 
38 {
39  fCurveResolution=CurveRes;
40 }
41 
42 //----------------------------------------------------------------------
43 // Destructor.
44 //
46 {
47 }
48 
49 
50 //----------------------------------------------------------------------
51 // Find the total length of one bezier segment connecting two seeds
52 // using a brute force integration
53 //
54 
56 {
57  double Length=0;
58  std::vector<TVector3> BezierPoints = GetBezierPoints(s1, s2, fCurveResolution);
59  for(unsigned int p=0; p!=BezierPoints.size()-1; ++p)
60  {
61  Length+=(BezierPoints.at(p+1)-BezierPoints.at(p)).Mag();
62  }
63  return Length;
64 }
65 
66 
67 //----------------------------------------------------------------------
68 // Helper method for interpolation - find optimal scales for
69 // direction vectors
70 //
71 
72 void BezierCurveHelper::GetDirectionScales(double * Pt1, double * Pt2, double * Dir1, double * Dir2, double * Scales)
73 {
74 
75  double PtSepVec[3];
76  for(int i=0; i!=3; ++i) PtSepVec[i]=Pt2[i]-Pt1[i];
77 
78  double PtSep = pow(
79  pow(PtSepVec[0],2) +
80  pow(PtSepVec[1],2) +
81  pow(PtSepVec[2],2),0.5);
82 
83  double Dir1Length = pow(Dir1[0]*Dir1[0]+
84  Dir1[1]*Dir1[1]+
85  Dir1[2]*Dir1[2],0.5);
86 
87  double Dir2Length = pow(Dir2[0]*Dir2[0]+
88  Dir2[1]*Dir2[1]+
89  Dir2[2]*Dir2[2],0.5);
90 
91  if((PtSepVec[0]*Dir1[0]+PtSepVec[1]*Dir1[1]+PtSepVec[2]*Dir1[2])>0)
92  Scales[0] = PtSep / (3.*Dir1Length);
93  else
94  Scales[0] = 0 - PtSep / (3.*Dir1Length);
95 
96  if((PtSepVec[0]*Dir2[0]+PtSepVec[1]*Dir2[1]+PtSepVec[2]*Dir2[2])>0)
97  Scales[1] = 0 - PtSep / (3.*Dir2Length);
98  else
99  Scales[1] = PtSep / (3.*Dir2Length);
100 
101 }
102 
103 
104 //----------------------------------------------------------------------
105 // Interpolate point between two seeds and return as double[3]
106 //
107 
108 void BezierCurveHelper::GetBezierPointXYZ(recob::Seed const& s1, recob::Seed const& s2, float s, double * xyz)
109 {
110  TVector3 BezierPoint = GetBezierPoint(s1, s2, s);
111  xyz[0]=BezierPoint[0];
112  xyz[1]=BezierPoint[1];
113  xyz[2]=BezierPoint[2];
114 
115 }
116 
117 
118 //----------------------------------------------------------------------
119 // Interpolate point between two seeds and return as a TVector3
120 //
121 
122 TVector3 BezierCurveHelper::GetBezierPoint(recob::Seed const& s1, recob::Seed const& s2, float s)
123 {
124  return GetBezierPointCubic(s1, s2, s);
125 }
126 
127 
128 //-----------------------------------------------------------------------
129 
131 {
132  TVector3 ReturnVec3;
133 
134  double Pt1[3], Pt2[3], Dir1[3], Dir2[3], Mid1[3], Mid2[3], Mid3[3], Dummy[3];
135  s1.GetDirection(Dir1, Dummy);
136  s2.GetDirection(Dir2, Dummy);
137  s1.GetPoint(Pt1, Dummy);
138  s2.GetPoint(Pt2, Dummy);
139 
140  if(s<=0.) return TVector3(Pt1[0],Pt1[1],Pt1[2]);
141  if(s>=1.) return TVector3(Pt2[0],Pt2[1],Pt2[2]);
142 
143  TVector3 pt1(Pt1[0],Pt1[1],Pt1[2]);
144  TVector3 pt2(Pt2[0],Pt2[1],Pt2[2]);
145  TVector3 dir1(Dir1[0],Dir1[1],Dir1[2]);
146  TVector3 dir2(Dir2[0],Dir2[1],Dir2[2]);
147 
148  double lambda1 = (pt1-pt2).Dot(dir1-dir2)/(pow(dir2.Dot(dir1),2)-dir2.Mag2()*dir1.Mag2());
149  double lambda2 = (pt2-pt1).Dot(dir2-dir1)/(pow(dir1.Dot(dir2),2)-dir1.Mag2()*dir2.Mag2());
150 
151 
152  int Sign1, Sign2;
153 
154  if(lambda1>0) Sign1=1;
155  else Sign1=-1;
156 
157  if(lambda2>0) Sign2=1;
158  else Sign2=-1;
159 
160  double ns=1.-s;
161  for(int i=0; i!=3; i++)
162  {
163  Mid1[i]=Pt1[i] + Sign1*Dir1[i];
164  Mid2[i]=0.5*(Pt1[i] + lambda1 * Dir1[i] + Pt2[i] +lambda2 * Dir2[i]);
165  Mid3[i]=Pt2[i] - Sign2*Dir2[i];
166  ReturnVec3[i]=
167  ns*ns*ns*ns * Pt1[i]
168  + 4.*ns*ns*ns*s * Mid1[i]
169  + 6.*ns*ns*s*s * Mid2[i]
170  + 4.*ns*s*s*s * Mid3[i]
171  + s*s*s*s * Pt2[i];
172  }
173 
174  return ReturnVec3;
175 
176 }
177 
178 
179 //-----------------------------------------------------------------------
180 
182 {
183  TVector3 ReturnVec3;
184 
185  double Pt1[3], Pt2[3], Dir1[3], Dir2[3], Mid1[3], Mid2[3], Dummy[3];
186  s1.GetDirection(Dir1, Dummy);
187  s2.GetDirection(Dir2, Dummy);
188  s1.GetPoint(Pt1, Dummy);
189  s2.GetPoint(Pt2, Dummy);
190 
191  if(s<=0.) return TVector3(Pt1[0],Pt1[1],Pt1[2]);
192  if(s>=1.) return TVector3(Pt2[0],Pt2[1],Pt2[2]);
193 
194 
195  double DirScales[2];
196  GetDirectionScales(Pt1,Pt2,Dir1,Dir2,DirScales);
197 
198  double ns=1.-s;
199  for(int i=0; i!=3; i++)
200  {
201  Mid1[i]=Pt1[i]+Dir1[i]*DirScales[0];
202  Mid2[i]=Pt2[i]+Dir2[i]*DirScales[1];
203  ReturnVec3[i]=
204  ns * ns * ns * Pt1[i]
205  + 3.* ns * ns * s * Mid1[i]
206  + 3.* ns * s * s * Mid2[i]
207  + s * s * s * Pt2[i];
208  }
209 
210 
211  return ReturnVec3;
212 
213 
214 
215 }
216 
217 
218 
219 //----------------------------------------------------------------------
220 // Interpolate a whole vector of points between two seeds - more
221 // efficient than doing each one separately
222 //
223 
224 
225 std::vector<TVector3> BezierCurveHelper::GetBezierPoints(recob::Seed const& s1, recob::Seed const& s2, int N)
226 {
227  return GetBezierPointsCubic(s1, s2, N);
228 }
229 
230 
231 //--------------------------------------------
232 
233 std::vector<TVector3> BezierCurveHelper::GetBezierPointsCubic(recob::Seed const& s1, recob::Seed const& s2, int N)
234 {
235 
236  std::vector<TVector3> ReturnVec;
237  ReturnVec.resize(N);
238 
239  double Pt1[3], Pt2[3], Dir1[3], Dir2[3], Mid1[3], Mid2[3], Dummy[3];
240  s1.GetDirection(Dir1, Dummy);
241  s2.GetDirection(Dir2, Dummy);
242  s1.GetPoint(Pt1, Dummy);
243  s2.GetPoint(Pt2, Dummy);
244 
245  double DirScales[2];
246  GetDirectionScales(Pt1,Pt2,Dir1,Dir2,DirScales);
247 
248 
249  for(int i=0; i!=3; i++)
250  {
251  Mid1[i]=Pt1[i]+Dir1[i]*DirScales[0];
252  Mid2[i]=Pt2[i]+Dir2[i]*DirScales[1];
253  for(int p=0; p!=N; p++)
254  {
255  double t = float(p) / float(N-1);
256  double nt = 1.-t;
257  ReturnVec.at(p)[i] =
258  nt*nt*nt * Pt1[i]
259  + 3.*nt*nt*t * Mid1[i]
260  + 3.*nt*t*t * Mid2[i]
261  + t*t*t * Pt2[i];
262  }
263  }
264 
265  return ReturnVec;
266 }
267 
268 
269 //-------------------------------------------------
270 
271 std::vector<TVector3> BezierCurveHelper::GetBezierPointsQuartic(recob::Seed const& s1, recob::Seed const& s2, int N)
272 {
273 
274  std::vector<TVector3> ReturnVec;
275  ReturnVec.resize(N);
276 
277  double Pt1[3], Pt2[3], Dir1[3], Dir2[3], Mid1[3], Mid2[3], Mid3[3], Dummy[3];
278  s1.GetDirection(Dir1, Dummy);
279  s2.GetDirection(Dir2, Dummy);
280  s1.GetPoint(Pt1, Dummy);
281  s2.GetPoint(Pt2, Dummy);
282 
283  TVector3 pt1(Pt1[0],Pt1[1],Pt1[2]);
284  TVector3 pt2(Pt2[0],Pt2[1],Pt2[2]);
285  TVector3 dir1(Dir1[0],Dir1[1],Dir1[2]);
286  TVector3 dir2(Dir2[0],Dir2[1],Dir2[2]);
287 
288 
289  double lambda1 = (pt1-pt2).Dot(dir1-dir2)/(pow(dir2.Dot(dir1),2)-dir2.Mag2()*dir1.Mag2());
290  double lambda2 = (pt2-pt1).Dot(dir2-dir1)/(pow(dir1.Dot(dir2),2)-dir1.Mag2()*dir2.Mag2());
291 
292  int Sign1, Sign2;
293 
294  if(lambda1>0) Sign1=1;
295  else Sign1=-1;
296 
297  if(lambda2>0) Sign2=1;
298  else Sign2=-1;
299 
300  for(int i=0; i!=3; i++)
301  {
302 
303 
304  Mid1[i]=Pt1[i] + Sign1*Dir1[i];
305  Mid2[i]=0.5*(Pt1[i] + lambda1 * Dir1[i] + Pt2[i] +lambda2 * Dir2[i]);
306  Mid3[i]=Pt2[i] - Sign2*Dir2[i];
307  for(int p=0; p!=N; p++)
308  {
309  double t = float(p) / float(N-1);
310  double nt = 1.-t;
311  ReturnVec.at(p)[i] =
312  nt*nt*nt*nt * Pt1[i]
313  + 4.*nt*nt*nt*t * Mid1[i]
314  + 6.*nt*nt*t*t * Mid2[i]
315  + 4.*nt*t*t*t * Mid3[i]
316  + t*t*t*t * Pt2[i];
317 
318  }
319  }
320 
321  return ReturnVec;
322 }
323 
324 
325 }
Float_t s
Definition: plot.C:23
TVector3 GetBezierPointQuartic(recob::Seed const &s1, recob::Seed const &s2, float t)
TVector3 GetBezierPoint(recob::Seed const &s1, recob::Seed const &s2, float t)
Declaration of signal hit object.
void GetPoint(double *Pt, double *Err) const
Definition: Seed.cxx:112
TVector3 GetBezierPointCubic(recob::Seed const &s1, recob::Seed const &s2, float t)
std::vector< TVector3 > GetBezierPointsCubic(recob::Seed const &s1, recob::Seed const &s2, int N=100)
Service for finding 3D track seeds.
double GetSegmentLength(recob::Seed const &s1, recob::Seed const &s2)
void GetDirectionScales(double *Pt1, double *Pt2, double *Dir1, double *Dir2, double *Scales)
void GetBezierPointXYZ(recob::Seed const &s1, recob::Seed const &s2, float t, double *xyz)
std::vector< TVector3 > GetBezierPoints(recob::Seed const &s1, recob::Seed const &s2, int N=100)
void GetDirection(double *Dir, double *Err) const
Definition: Seed.cxx:102
std::vector< TVector3 > GetBezierPointsQuartic(recob::Seed const &s1, recob::Seed const &s2, int N=100)