EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
3d.cxx
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file 3d.cxx
1 /* -------------------------------------------------------------------------- */
2 /* 3d.c */
3 /* */
4 /* A useful collection of 3d algebra routines. One day should be */
5 /* assembly-level optimized (SSE usage). BLAS? */
6 /* */
7 /* A.Kisselev, PNPI, St.Petersburg, Russia. */
8 /* e-mail: kisselev@hermes.desy.de */
9 /* -------------------------------------------------------------------------- */
10 
11 #include <cmath>
12 #include <cstring>
13 
14 #include <ayk.h>
15 #include <3d.h>
16 
17 /* ========================================================================== */
18 /* Calculates crossing parameters of 2 straight lines; assumes, that */
19 /* n1,n2 are normalized to '1'; assumes that lines are 'measured' */
20 /* with the same accuracy; 'crs' is the line parametrized in a way */
21 /* that '*crs->x' is a point inbetween 2 lines and '*crs->nx' is it's */
22 /* normalized vector (NB: it is guaranteed to point from l1 to l2); */
23 /* then '*rx' is the length of the 'bridge'; */
24 
25 int cross_l_l(const t_3d_line *l1, const t_3d_line *l2, t_3d_line *crs, double *rx,
26  double *theta, double tt[])
27 {
28  double t1, t2, a, b, c = l1->nx.Dot(l2->nx);//smul_v_v(l1->nx, l2->nx);
29  TVector3 xy, q1, q2, _dd_;
30  int config = 0, exact_crossing_flag = 0;
31 
32  /* Check 2 line configuration; */
33  if (l1->nx == l2->nx) config = _PARALLEL_;
34 
35  if (crs || rx || tt)
36  {
37  xy = l1->x - l2->x;//sub_v_v(xy, l1->x, l2->x);
38 
39  a = xy.Dot(l1->nx);//smul_v_v(xy, l1->nx);
40  b = xy.Dot(l2->nx);//smul_v_v(xy, l2->nx);
41 
42  /* Just take any definite 't2' in case if lines are parallel; */
43  /* Since such occasions must be rare don't want to arrange */
44  /* special branch; */
45  t2 = config ? 0. : (b - a*c)/(1 - SQR(c));
46  t1 = t2*c - a;
47 
48  if (tt)
49  {
50  tt[0] = t1;
51  tt[1] = t2;
52  } /*if*/
53 
54  /* Calculate closest to each other points on both straight lines; */
55  q1 = t1 * l1->nx + l1->x;//mul_s_v(q1, t1, l1->nx); add_v_v(q1, q1, l1->x);
56  q2 = t2 * l2->nx + l2->x;//mul_s_v(q2, t2, l2->nx); add_v_v(q2, q2, l2->x);
57 
58  /* Vector connecting 2 straight lines; */
59  _dd_ = q2 - q1;//sub_v_v(_dd_, q2, q1);
60 
61  /* Point between 2 lines; */
62  if (crs)
63  {
64  if (config)
65  /* Anyway makes no sense --> make it definite; */
66  VZERO(crs->x);//vzero(crs->x);
67  else
68  crs->x = 0.5 * (q1 + q2);
69  //{
70  //add_v_v(crs->x, q1, q2);
71  //mul_s_v(crs->x, .5, crs->x);
72  //} /*if*/
73 
74  crs->nx = _dd_;//vcopy(crs->nx, _dd_);
75 
76  /* If normalization fails (crossing lines), */
77  /* prefer to set to the defined values; */
78  //if (normalize_v(crs->nx))
79  if (!crs->nx.Mag())
80  {
81  exact_crossing_flag = 1;
82  VZERO(crs->nx);//vzero(crs->nx);
83  crs->nx[_Z_] = 1.;
84  }
85  else
86  crs->nx.SetMag(1.0);
87  } /*if*/
88 
89  /* Length of the 'bridging' vector; */
90  //if (rx) *rx = exact_crossing_flag ? 0. : len_v(_dd_);
91  if (rx) *rx = exact_crossing_flag ? 0. : _dd_.Mag();
92  } /*if*/
93 
94  /* Angle between 2 lines; */
95  if (theta) *theta = rad2deg(acos(c));
96 
97  return config;
98 } /* cross_l_l */
99 
100 /* ========================================================================== */
101 /* Calculates crossing point of the plane and straight line; */
102 /* assumes, that np,nl are normalized to '1'; */
103 
104 int cross_p_l(const t_3d_plane *pl, const t_3d_line *ll, TVector3 &crs)
105 {
106  int config = 0;
107  double a, c = pl->nx.Dot(ll->nx);//smul_v_v(pl->nx, ll->nx);
108  TVector3 qq;//, save;
109 
110  //printf("c: %f\n", c);
111 
112  qq = pl->x - ll->x;//sub_v_v(qq, pl->x, ll->x);
113  a = qq.Dot(pl->nx);//smul_v_v(qq, pl->nx);
114 
115  /* Check configuration; */
116  if (!c)
117  {
118  config = _PARALLEL_;
119  if (!a) config = _BELONG_;
120 
121  //assert(0);
122  /* Anyway makes no sense --> make it definite; */
123  VZERO(crs);//vzero(crs);
124  }
125  else
126  crs = ll->x + (a/c) * ll->nx;
127  //{
128  // /* May want to reparametrize 'll' => 'crs' may be just */
129  // /* 'll->x' => need to save it; */
130  //vcopy(save, ll->x);
131  //mul_s_v(crs, a/c, ll->nx);
132  //add_v_v(crs, crs, save);
133  //} /*if*/
134 
135  return config;
136 } /* cross_p_l */
137 
138 /* ========================================================================== */
139 /* Constructs line using 2 space points; always uses x1 for the */
140 /* parametrization; 'nx' is guaranteed to point from x1 to x2; */
141 
142 #if _OLD_
143 //
144 // --> FIXME: has never been checked since conversion to ROOT, etc;
145 //
146 t_3d_line::t_3d_line(TVector3 &x1, TVector3 &x2)
147 {
148  if (x1 == x2)
149  {
150  VZERO(x); VZERO(nx);
151  //return _COINSIDE_;
152  }
153  else
154  {
155  x = x1;//vcopy(line->x, x1);
156  nx = x2 - x1;//sub_v_v(line->nx, x2, x1);
157  nx.SetMag(1.0);//normalize_v(line->nx);
158  } //if
159 } // t_3d_line::t_3d_line()
160 #endif
161 
162 /* ========================================================================== */
163 /* Conctructs plane using line and point in space; always uses xx */
164 /* for the plane parametrization; */
165 
167 {
168  TVector3 vv;
169  double t0;
170 
171  /* Find minimal distance point on the line; */
172  vv = xx - ll->x;//sub_v_v(vv, xx, ll->x);
173  t0 = vv.Dot(ll->nx);//smul_v_v(vv, ll->nx);
174  vv = ll->x + t0 * ll->nx;
175  //mul_s_v(vv, t0, ll->nx);
176  //add_v_v(vv, vv, ll->x);
177 
178  /* Check that original point is not sitting on the line; */
179  if (vv == xx) return _BELONG_;
180 
181  /* Build normalized vector along this bridge; */
182  vv -= xx;//sub_v_v(vv, vv, xx);
183 
184  /* And assign the resulting plane structure; */
185  pl->x = xx;//vcopy(pl->x, xx);
186  pl->nx = ll->nx.Cross(vv);//vmul_v_v(pl->nx, ll->nx, vv);
187  pl->nx.SetMag(1.0);//normalize_v(pl->nx);
188 
189  return 0;
190 } /* build_plane_from_point_and_line */
191 
192 /* ========================================================================== */
193 /* NB: Modified in June'2008; perhaps older version was correct as well; */
194 
195 double point_to_line_dist(TVector3 &xx, t_3d_line *ll, TVector3 &bridge)
196 {
197  TVector3 diff, pro, orth;
198 
199  diff = xx - ll->x;//sub_v_v(diff, xx, ll->x);
200  //pro = smul_v_v(diff, ll->nx) * ll->nx;//mul_s_v(pro, smul_v_v(diff, ll->nx), ll->nx);
201  pro = diff.Dot(ll->nx) * ll->nx;//mul_s_v(pro, smul_v_v(diff, ll->nx), ll->nx);
202 
203  orth = diff - pro;//sub_v_v(orth, diff, pro);
204 
205  //if (bridge)
206  bridge = orth;//VCOPY(bridge, orth);
207 
208  return orth.Mag();//return len_v(orth);
209 } /* point_to_line_dist */
210 
211 /* ========================================================================== */
212 /* Well, this is sort of trivial; still useful; */
213 
214 double point_to_plane_dist(TVector3 &xx, t_3d_plane *pl)
215 {
216  TVector3 vv;
217 
218  vv = xx - pl->x;//sub_v_v(vv, xx, pl->x);
219 
220  return fabs(vv.Dot(pl->nx));//smul_v_v(vv, pl->nx));
221 } /* point_to_plane_dist */
222 
223 /* ========================================================================== */
224 
226 {
227  double dist;
228 
229  cross_l_l(l1, l2, NULL, &dist, NULL, NULL);
230 
231  return dist;
232 } /* line_to_line_dist */
233 
234 /* ========================================================================== */
235 #if _OLD_
236 t_3d_line parametrize_straight_line(double S[4], double z)
237 {
238  double norm = sqrt(1. + SQR(S[2]) + SQR(S[3]));
239 
240  return t_3d_line(TVector3(S[0], S[1], z), TVector3(S[2]/norm, S[3]/norm, 1./norm));
241 } /* parametrize_straight_line */
242 #else
243 t_3d_line::t_3d_line(double S[4], double z)
244 {
245  double norm = sqrt(1. + SQR(S[2]) + SQR(S[3]));
246 
247  x = TVector3(S[0], S[1], z);
248  nx = TVector3(S[2]/norm, S[3]/norm, 1./norm);
249 } // t_3d_line::t_3d_line()
250 #endif
251 
252 /* ========================================================================== */
253 
254 int deparametrize_straight_line(t_3d_line *line, double z, double S[4])
255 {
256  TVector3 crs;
257  t_3d_plane parametrization_plane(TVector3(0., 0., z), TVector3(0., 0., 1.));
258 
259  if (cross_p_l(&parametrization_plane, line, crs)) return -1;
260 
261  S[0] = crs[_X_];
262  S[1] = crs[_Y_];
263 
264  if (!line->nx[_Z_]) return -1;
265 
266  S[2] = line->nx[_X_]/line->nx[_Z_];
267  S[3] = line->nx[_Y_]/line->nx[_Z_];
268 
269  return 0;
270 } /* deparametrize_straight_line */
271 
272 /* ========================================================================== */