HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
UT_CovarianceMatrix.h
Go to the documentation of this file.
1 /*
2  * PROPRIETARY INFORMATION. This software is proprietary to
3  * Side Effects Software Inc., and is not to be reproduced,
4  * transmitted, or disclosed in any way without written permission.
5  *
6  * COMMENTS:
7  * Covariance Matrix calculations for points, segments, and triangles
8  * in 2 and 3 dimensions. The point covariance is the usual one often
9  * computed in geometry processing. The segment and triangle versions
10  * integrate it over all the points of all the given segments or
11  * triangles.
12  *
13  * The calculations are taken from the thesis of Stefan Gottschalk:
14  * "Collision Queries using Oriented Bounding Boxes",
15  * pages 52 and 57.
16  *
17  */
18 
19 #ifndef __UT_CovarianceMatrix__
20 #define __UT_CovarianceMatrix__
21 
22 #include "UT_Accumulator.h"
23 #include "UT_Array.h"
24 #include "UT_Matrix2.h"
25 #include "UT_SymMatrix3.h"
26 #include "UT_Vector2.h"
27 #include "UT_Vector3.h"
28 
29 #include <SYS/SYS_Types.h>
30 
31 
32 namespace UT_CovarianceMatrix
33 {
34 
35 // Calculate a 2x2 covariance matrix for a set of points in the plane.
36 // PT_POS must implemented a single parameter operator()(int i) to return
37 // a UT_Vector2T<T> for integer point number parameter values
38 // 0, ..., num_pts - 1.
39 
40 template <typename T, typename PT_POS>
42 pointCovariance2(int num_pts, PT_POS pt_pos,
43  UT_Vector2T<T> *calculated_centroid = nullptr)
44 {
45  UT_Vector2T<T> our_centroid;
46  auto &centroid = calculated_centroid ? *calculated_centroid : our_centroid;
47 
49 
50  for (int i = 0, ie = num_pts; i < ie; i++)
51  ctr += pt_pos(i);
52 
53  centroid = ctr.sum() / num_pts;
54 
55  UT::Accumulator<T> cxx(T(0)), cxy(T(0)), cyy(T(0));
56 
57  for (int i = 0, ie = num_pts; i < ie; i++)
58  {
59  auto p = pt_pos(i) - centroid;
60  cxx += p.x() * p.x();
61  cxy += p.x() * p.y();
62  cyy += p.y() * p.y();
63  }
64 
65  return { cxx.sum(), cxy.sum(), cxy.sum(), cyy.sum() };
66 }
67 
68 // Calculate a 3x3 covariance matrix for a set of points in the space.
69 // PT_POS must implemented a single parameter operator()(int i) to return
70 // a UT_Vector3T<T> for integer point number parameter values
71 // 0, ..., num_pts - 1.
72 
73 template <typename T, typename PT_POS>
75 pointCovariance3(int num_pts, PT_POS pt_pos,
76  UT_Vector3T<T> *calculated_centroid = nullptr)
77 {
78  UT_Vector3T<T> our_centroid;
79  auto &centroid = calculated_centroid ? *calculated_centroid : our_centroid;
80 
82 
83  for (int i = 0, ie = num_pts; i < ie; i++)
84  ctr += pt_pos(i);
85 
86  centroid = ctr.sum() / num_pts;
87 
88  UT::Accumulator<T> cxx(T(0)), cxy(T(0)), cxz(T(0));
89  UT::Accumulator<T> cyy(T(0)), cyz((0)), czz(T(0));
90 
91  for (int i = 0, ie = num_pts; i < ie; i++)
92  {
93  auto p = pt_pos(i) - centroid;
94 
95  cxx += p.x() * p.x();
96  cxy += p.x() * p.y();
97  cxz += p.x() * p.z();
98  cyy += p.y() * p.y();
99  cyz += p.y() * p.z();
100  czz += p.z() * p.z();
101  }
102 
103  return { cxx.sum(), cxy.sum(), cyy.sum(), cxz.sum(), cyz.sum(), czz.sum() };
104 }
105 
106 // Calculate a 2x2 covariance matrix for a set of segments in the plane.
107 // PT_POS must implemented a single parameter operator()(int i) called
108 // with argument in range 0, ..., 2 * num_segs - 1.
109 
110 template <typename T, typename PT_POS>
112 segmentCovariance2(int num_segs, PT_POS seg_pt_pos,
113  UT_Vector2T<T> *calculated_centroid = nullptr,
114  T *calculated_length = nullptr)
115 {
116  UT_Vector2T<T> our_centroid;
117  auto &centroid = calculated_centroid ? *calculated_centroid : our_centroid;
118 
120  UT::Accumulator<T> len(T(0));
121 
122  UT_Array<T> seg_len;
123  UT_Array< UT_Vector2T<T> > seg_centroid_x2;
124 
125  seg_len.setSizeNoInit(num_segs);
126  seg_centroid_x2.setSizeNoInit(num_segs);
127 
128  for (int s = 0, se = num_segs; s < se; s++)
129  {
130  auto p = seg_pt_pos(2 * s);
131  auto q = seg_pt_pos(2 * s + 1);
132 
133  seg_centroid_x2(s) = p + q;
134  seg_len(s) = (q - p).length();
135  len += seg_len(s);
136  ctr += (seg_len(s) * seg_centroid_x2(s));
137  }
138 
139  T l = len.sum();
140  if (calculated_length)
141  *calculated_length = l;
142 
143  auto centroid_x2 = ctr.sum() / l;
144 
145  if (l == 0.0)
146  return { T(0), T(0), T(0), T(0) };
147 
148  // Centroid of the all triangles:
149  centroid = T(0.5) * centroid_x2;
150 
151  UT::Accumulator<T> cxx(T(0)), cxy(T(0)), cyy(T(0));
152  for (int s = 0, se = num_segs; s < se; s++)
153  {
154  auto p = seg_pt_pos(2 * s) - centroid;
155  auto q = seg_pt_pos(2 * s + 1) - centroid;
156  auto scx2 = seg_centroid_x2(s) - centroid_x2;
157 
158  auto sl = seg_len(s);
159 
160 #ifdef STANDARD_SUM
161  cxx += sl * (scx2.x() * scx2.x() + p.x() * p.x() + q.x() * q.x());
162  cxy += sl * (scx2.x() * scx2.y() + p.x() * p.y() + q.x() * q.y());
163  cyy += sl * (scx2.y() * scx2.y() + p.y() * p.y() + q.y() * q.y());
164 #else
165  auto lp = sl * p;
166  auto lq = sl * q;
167  auto lscx2 = sl * scx2;
168 
169  cxx += lscx2.x() * scx2.x();
170  cxx += lp.x() * p.x();
171  cxx += lq.x() * q.x();
172 
173  cxy += lscx2.x() * scx2.y();
174  cxy += lp.x() * p.y();
175  cxy += lq.x() * q.y();
176 
177  cyy += lscx2.y() * scx2.y();
178  cyy += lp.y() * p.y();
179  cyy += lq.y() * q.y();
180 #endif
181  }
182 
183  l *= T(6.0);
184 
185  return { cxx.sum() / l, cxy.sum() / l, cxy.sum() / l, cyy.sum() / l };
186 }
187 
188 // Calculate a 3x3 covariance matrix for a set of segments in the space.
189 // PT_POS must implemented a single parameter operator()(int i) called
190 // with argument in range 0, ..., 2 * num_segs - 1.
191 
192 template <typename T, typename PT_POS>
194 segmentCovariance3(int num_segs, PT_POS seg_pt_pos,
195  UT_Vector3T<T> *calculated_centroid = nullptr,
196  T * calculated_length = nullptr)
197 {
198  UT_Vector3T<T> our_centroid;
199  auto &centroid = calculated_centroid ? *calculated_centroid : our_centroid;
200 
202  UT::Accumulator<T> len(T(0));
203 
204  UT_Array<T> seg_len;
205  UT_Array< UT_Vector3T<T> > seg_centroid_x2;
206 
207  seg_len.setSizeNoInit(num_segs);
208  seg_centroid_x2.setSizeNoInit(num_segs);
209 
210  for (int s = 0, se = num_segs; s < se; s++)
211  {
212  auto p = seg_pt_pos(2 * s);
213  auto q = seg_pt_pos(2 * s + 1);
214 
215  seg_centroid_x2(s) = p + q;
216  seg_len(s) = (q - p).length();
217  len += seg_len(s);
218  ctr += (seg_len(s) * seg_centroid_x2(s));
219  }
220 
221  T l = len.sum();
222  if (calculated_length)
223  *calculated_length = l;
224 
225  if (l == T(0))
226  return { T(0), T(0), T(0), T(0), T(0), T(0) };
227 
228  auto centroid_x2 = ctr.sum() / l;
229 
230  // Centroid of the all triangles:
231  centroid = T(0.5) * centroid_x2;
232 
233  UT::Accumulator<T> cxx(T(0)), cxy(T(0)), cxz(T(0));
234  UT::Accumulator<T> cyy(T(0)), cyz((0)), czz(T(0));
235 
236  for (int s = 0, se = num_segs; s < se; s++)
237  {
238  auto p = seg_pt_pos(2 * s) - centroid;
239  auto q = seg_pt_pos(2 * s + 1) - centroid;
240 
241  auto scx2 = seg_centroid_x2(s) - centroid_x2;
242  auto sl = seg_len(s);
243 
244 #ifdef STANDARD_SUM
245  cxx += sl * (scx2.x() * scx2.x() + p.x() * p.x() + q.x() * q.x());
246  cxy += sl * (scx2.x() * scx2.y() + p.x() * p.y() + q.x() * q.y());
247  cxz += sl * (scx2.x() * scx2.z() + p.x() * p.z() + q.x() * q.z());
248  cyy += sl * (scx2.y() * scx2.y() + p.y() * p.y() + q.y() * q.y());
249  cyz += sl * (scx2.y() * scx2.z() + p.y() * p.z() + q.y() * q.z());
250  czz += sl * (scx2.z() * scx2.z() + p.z() * p.z() + q.z() * q.z());
251 #else
252  auto lp = sl * p;
253  auto lq = sl * q;
254  auto lscx2 = sl * scx2;
255 
256  cxx += lscx2.x() * scx2.x();
257  cxx += lp.x() * p.x();
258  cxx += lq.x() * q.x();
259 
260  cxy += lscx2.x() * scx2.y();
261  cxy += lp.x() * p.y();
262  cxy += lq.x() * q.y();
263 
264  cxy += lscx2.x() * scx2.z();
265  cxy += lp.x() * p.z();
266  cxy += lq.x() * q.z();
267 
268  cyy += lscx2.y() * scx2.y();
269  cyy += lp.y() * p.y();
270  cyy += lq.y() * q.y();
271 
272  cyz += lscx2.y() * scx2.z();
273  cyz += lp.y() * p.z();
274  cyz += lq.y() * q.z();
275 
276  czz += lscx2.z() * scx2.z();
277  czz += lp.z() * p.z();
278  czz += lq.z() * q.z();
279 #endif
280  }
281 
282  l *= T(6.0);
283 
284  return { cxx.sum() / l, cxy.sum() / l, cyy.sum() / l,
285  cxz.sum() / l, cyz.sum() / l, czz.sum() / l };
286 }
287 
288 // Calculate a 2x2 covariance matrix for a set of triangles in the plane.
289 // PT_POS must implemented a single parameter operator()(int i) called
290 // with argument in range 0, ..., 3 * num_tris - 1.
291 
292 template <typename T, typename PT_POS>
294 triangleCovariance2(int num_tris, PT_POS tri_pt_pos,
295  UT_Vector2T<T> *calculated_centroid = nullptr,
296  T *calculated_area = nullptr)
297 {
298  UT_Vector2T<T> our_centroid;
299  auto &centroid = calculated_centroid ? *calculated_centroid : our_centroid;
300 
302  UT::Accumulator<T> area_x2(T(0));
303 
304  UT_Array<T> tri_area_x2; // triangle area x 2
305  UT_Array< UT_Vector2T<T> > tri_centroid_x3; // triangle centroid x 3
306 
307  tri_area_x2.setSizeNoInit(num_tris);
308  tri_centroid_x3.setSizeNoInit(num_tris);
309 
310  for (int t = 0, te = num_tris; t < te; t++)
311  {
312  auto t0 = 3 * t;
313  auto p = tri_pt_pos(t0);
314  auto q = tri_pt_pos(t0 + 1);
315  auto r = tri_pt_pos(t0 + 2);
316 
317  tri_centroid_x3(t) = (p + q) + r;
318  tri_area_x2(t) = SYSabs((q.x() - p.x()) * (r.y() - p.y())
319  - (q.y() - p.y()) * (r.x() - p.x()));
320 
321  area_x2 += tri_area_x2(t);
322  ctr += (tri_area_x2(t) * tri_centroid_x3(t));
323  }
324 
325  auto a = area_x2.sum();
326  if (calculated_area)
327  *calculated_area = a * T(0.5);
328 
329  if (a == T(0))
330  return { T(0), T(0), T(0), T(0) };
331 
332  auto centroid_x3 = ctr.sum() / a;
333 
334  // Centroid of the all triangles:
335  centroid = centroid_x3 / 3.0;
336 
337  UT::Accumulator<T> cxx(T(0)), cxy(T(0)), cyy(T(0));
338 
339  for (int t = 0, te = num_tris; t < te; t++)
340  {
341  auto t0 = 3 * t;
342  auto p = tri_pt_pos(t0) - centroid;
343  auto q = tri_pt_pos(t0 + 1) - centroid;
344  auto r = tri_pt_pos(t0 + 2) - centroid;
345 
346  auto tcx3 = tri_centroid_x3(t) - centroid_x3;
347  auto tax2 = tri_area_x2(t);
348 
349 #ifdef STANDARD_SUM
350  cxx += tax2 * (tcx3.x() * tcx3.x()
351  + p.x() * p.x() + q.x() * q.x() + r.x() * r.x());
352  cxy += tax2 * (tcx3.x() * tcx3.y()
353  + p.x() * p.y() + q.x() * q.y() + r.x() * r.y());
354  cyy += tax2 * (tcx3.y() * tcx3.y()
355  + p.y() * p.y() + q.y() * q.y() + r.y() * r.y());
356 #else
357  auto ap = tax2 * p;
358  auto aq = tax2 * q;
359  auto ar = tax2 * r;
360  auto atcx3 = tax2 * tcx3;
361 
362  cxx += atcx3.x() * tcx3.x();
363  cxx += ap.x() * p.x();
364  cxx += aq.x() * q.x();
365  cxx += ar.x() * r.x();
366 
367  cxy += atcx3.x() * tcx3.y();
368  cxy += ap.x() * p.y();
369  cxy += aq.x() * q.y();
370  cxy += ar.x() * r.y();
371 
372  cyy += atcx3.y() * tcx3.y();
373  cyy += ap.y() * p.y();
374  cyy += aq.y() * q.y();
375  cyy += ar.y() * r.y();
376 #endif
377  }
378 
379  a *= T(12.0);
380 
381  return { cxx.sum() / a, cxy.sum() / a, cxy.sum() / a, cyy.sum() / a };
382 }
383 
384 // Calculate a 3x3 covariance matrix for a set of triangles in the space.
385 // PT_POS must implemented a single parameter operator()(int i) called
386 // with argument in range 0, ..., 3 * num_tris - 1.
387 
388 template <typename T, typename PT_POS>
390 triangleCovariance3(int num_tris, PT_POS tri_pt_pos,
391  UT_Vector3T<T> *calculated_centroid = nullptr,
392  UT_Vector3T<T> *calculated_average_normal = nullptr,
393  T *calculated_area = nullptr)
394 {
395  UT_Vector3T<T> our_centroid;
396  auto &centroid = calculated_centroid ? *calculated_centroid : our_centroid;
397 
398  UT_Vector3T<T> our_average_normal;
399  auto &average_normal =
400  calculated_average_normal ? *calculated_average_normal
401  : our_average_normal;
402 
405 
406  UT::Accumulator<T> area_x2(T(0));
407 
408  UT_Array<T> tri_area_x2;
409  UT_Array< UT_Vector3T<T> > tri_centroid_x3;
410 
411  tri_area_x2.setSizeNoInit(num_tris);
412  tri_centroid_x3.setSizeNoInit(num_tris);
413 
414  for (int t = 0, te = num_tris; t < te; t++)
415  {
416  auto t0 = 3 * t;
417  auto p = tri_pt_pos(t0);
418  auto q = tri_pt_pos(t0 + 1);
419  auto r = tri_pt_pos(t0 + 2);
420 
421  tri_centroid_x3(t) = (p + q) + r;
422 
423  auto n = cross(q - p, r - p);
424 
425  // Add the cross product as unit normal weighted by (twice) tri area.
426  nml += n;
427 
428  tri_area_x2(t) = n.length();
429  area_x2 += tri_area_x2(t);
430 
431  ctr += (tri_area_x2(t) * tri_centroid_x3(t));
432  }
433 
434  T a = area_x2.sum();
435 
436  if (calculated_area)
437  *calculated_area = a * T(0.5);
438 
439  if (a == T(0))
440  return { T(0), T(0), T(0), T(0), T(0), T(0) };
441 
442  auto centroid_x3 = ctr.sum() / a;
443 
444  // Centroid of the all triangles:
445  centroid = centroid_x3 / 3.0;
446  average_normal = nml.sum() / a;
447 
448  UT::Accumulator<T> cxx(T(0)), cxy(T(0)), cxz(T(0));
449  UT::Accumulator<T> cyy(T(0)), cyz((0)), czz(T(0));
450 
451  for (int t = 0, te = num_tris; t < te; t++)
452  {
453  auto t0 = 3 * t;
454  auto p = tri_pt_pos(t0) - centroid;
455  auto q = tri_pt_pos(t0 + 1) - centroid;
456  auto r = tri_pt_pos(t0 + 2) - centroid;
457 
458  auto tcx3 = tri_centroid_x3(t) - centroid_x3;
459  auto tax2 = tri_area_x2(t);
460 
461 #ifdef STANDARD_SUM
462  cxx += tax2 * (tcx3.x() * tcx3.x()
463  + p.x() * p.x() + q.x() * q.x() + r.x() * r.x());
464  cxy += tax2 * (tcx3.x() * tcx3.y()
465  + p.x() * p.y() + q.x() * q.y() + r.x() * r.y());
466  cxz += tax2 * (tcx3.x() * tcx3.z()
467  + p.x() * p.z() + q.x() * q.z() + r.x() * r.z());
468  cyy += tax2 * (tcx3.y() * tcx3.y()
469  + p.y() * p.y() + q.y() * q.y() + r.y() * r.y());
470  cyz += tax2 * (tcx3.y() * tcx3.z()
471  + p.y() * p.z() + q.y() * q.z() + r.y() * r.z());
472  czz += tax2 * (tcx3.z() * tcx3.z()
473  + p.z() * p.z() + q.z() * q.z() + r.z() * r.z());
474 #else
475 
476  auto ap = tax2 * p;
477  auto aq = tax2 * q;
478  auto ar = tax2 * r;
479  auto atcx3 = tax2 * tcx3;
480 
481  cxx += atcx3.x() * tcx3.x();
482  cxx += ap.x() * p.x();
483  cxx += aq.x() * q.x();
484  cxx += ar.x() * r.x();
485 
486  cxy += atcx3.x() * tcx3.y();
487  cxy += ap.x() * p.y();
488  cxy += aq.x() * q.y();
489  cxy += ar.x() * r.y();
490 
491  cxz += atcx3.x() * tcx3.z();
492  cxz += ap.x() * p.z();
493  cxz += aq.x() * q.z();
494  cxz += ar.x() * r.z();
495 
496  cyy += atcx3.y() * tcx3.y();
497  cyy += ap.y() * p.y();
498  cyy += aq.y() * q.y();
499  cyy += ar.y() * r.y();
500 
501  cyz += atcx3.y() * tcx3.z();
502  cyz += ap.y() * p.z();
503  cyz += aq.y() * q.z();
504  cyz += ar.y() * r.z();
505 
506  czz += atcx3.z() * tcx3.z();
507  czz += ap.z() * p.z();
508  czz += aq.z() * q.z();
509  czz += ar.z() * r.z();
510 
511 #endif
512  }
513 
514  a *= T(12.0);
515 
516  return { cxx.sum() / a, cxy.sum() / a, cyy.sum() / a,
517  cxz.sum() / a, cyz.sum() / a, czz.sum() / a };
518 }
519 
520 } // namespace UT_CovarianceMatrix
521 
522 #endif
UT_Matrix2T< T > pointCovariance2(int num_pts, PT_POS pt_pos, UT_Vector2T< T > *calculated_centroid=nullptr)
UT_SymMatrix3T< T > triangleCovariance3(int num_tris, PT_POS tri_pt_pos, UT_Vector3T< T > *calculated_centroid=nullptr, UT_Vector3T< T > *calculated_average_normal=nullptr, T *calculated_area=nullptr)
void setSizeNoInit(exint newsize)
Definition: UT_Array.h:695
GLboolean GLboolean GLboolean GLboolean a
Definition: glcorearb.h:1222
GLdouble s
Definition: glad.h:3009
#define SYSabs(a)
Definition: SYS_Math.h:1572
GLuint GLsizei GLsizei * length
Definition: glcorearb.h:795
Generic symmetric 3x3 matrix.
Definition: UT_SymMatrix3.h:27
UT_Matrix2T< T > triangleCovariance2(int num_tris, PT_POS tri_pt_pos, UT_Vector2T< T > *calculated_centroid=nullptr, T *calculated_area=nullptr)
GLdouble GLdouble GLdouble q
Definition: glad.h:2445
3D Vector class.
2D Vector class.
Definition: UT_Vector2.h:159
GLdouble n
Definition: glcorearb.h:2008
UT_SymMatrix3T< T > segmentCovariance3(int num_segs, PT_POS seg_pt_pos, UT_Vector3T< T > *calculated_centroid=nullptr, T *calculated_length=nullptr)
GLdouble t
Definition: glad.h:2397
UT_Matrix2T< T > segmentCovariance2(int num_segs, PT_POS seg_pt_pos, UT_Vector2T< T > *calculated_centroid=nullptr, T *calculated_length=nullptr)
T sum() const
GLboolean r
Definition: glcorearb.h:1222
UT_SymMatrix3T< T > pointCovariance3(int num_pts, PT_POS pt_pos, UT_Vector3T< T > *calculated_centroid=nullptr)
SIM_DerVector3 cross(const SIM_DerVector3 &lhs, const SIM_DerVector3 &rhs)