FCL  0.6.0
Flexible Collision Library
BV_splitter-inl.h
1 /*
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2011-2014, Willow Garage, Inc.
5  * Copyright (c) 2014-2016, Open Source Robotics Foundation
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * * Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  * * Redistributions in binary form must reproduce the above
15  * copyright notice, this list of conditions and the following
16  * disclaimer in the documentation and/or other materials provided
17  * with the distribution.
18  * * Neither the name of Open Source Robotics Foundation nor the names of its
19  * contributors may be used to endorse or promote products derived
20  * from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33  * POSSIBILITY OF SUCH DAMAGE.
34  */
35 
38 #ifndef FCL_BV_SPLITTER_INL_H
39 #define FCL_BV_SPLITTER_INL_H
40 
41 #include "fcl/geometry/bvh/detail/BV_splitter.h"
42 
43 namespace fcl
44 {
45 
46 namespace detail
47 {
48 
49 //==============================================================================
50 template <typename BV>
51 BVSplitter<BV>::BVSplitter(SplitMethodType method)
52  : split_method(method)
53 {
54  // Do nothing
55 }
56 
57 //==============================================================================
58 template <typename BV>
60 {
61  // Do nothing
62 }
63 
64 //==============================================================================
65 template <typename BV>
67  Vector3<S>* vertices_, Triangle* tri_indices_, BVHModelType type_)
68 {
69  vertices = vertices_;
70  tri_indices = tri_indices_;
71  type = type_;
72 }
73 
74 //==============================================================================
75 template <typename BV>
77  const BV& bv, unsigned int* primitive_indices, int num_primitives)
78 {
79  switch(split_method)
80  {
81  case SPLIT_METHOD_MEAN:
82  computeRule_mean(bv, primitive_indices, num_primitives);
83  break;
84  case SPLIT_METHOD_MEDIAN:
85  computeRule_median(bv, primitive_indices, num_primitives);
86  break;
87  case SPLIT_METHOD_BV_CENTER:
88  computeRule_bvcenter(bv, primitive_indices, num_primitives);
89  break;
90  default:
91  std::cerr << "Split method not supported" << std::endl;
92  }
93 }
94 
95 //==============================================================================
96 template <typename S, typename BV>
97 struct ApplyImpl
98 {
99  static bool run(
100  const BVSplitter<BV>& splitter, const Vector3<S>& q)
101  {
102  return q[splitter.split_axis] > splitter.split_value;
103  }
104 };
105 
106 //==============================================================================
107 template <typename BV>
108 bool BVSplitter<BV>::apply(const Vector3<S>& q) const
109 {
110  return ApplyImpl<S, BV>::run(*this, q);
111 }
112 
113 //==============================================================================
114 template <typename S, typename BV>
116 {
117  static void run(
118  BVSplitter<BV>& splitter,
119  const BV& bv,
120  unsigned int* /*primitive_indices*/,
121  int /*num_primitives*/)
122  {
123  Vector3<S> center = bv.center();
124  int axis = 2;
125 
126  if(bv.width() >= bv.height() && bv.width() >= bv.depth())
127  axis = 0;
128  else if(bv.height() >= bv.width() && bv.height() >= bv.depth())
129  axis = 1;
130 
131  splitter.split_axis = axis;
132  splitter.split_value = center[axis];
133  }
134 };
135 
136 //==============================================================================
137 template <typename BV>
139  const BV& bv, unsigned int* primitive_indices, int num_primitives)
140 {
142  *this, bv, primitive_indices, num_primitives);
143 }
144 
145 //==============================================================================
146 template <typename S, typename BV>
148 {
149  static void run(
150  BVSplitter<BV>& splitter,
151  const BV& bv,
152  unsigned int* primitive_indices,
153  int num_primitives)
154  {
155  int axis = 2;
156 
157  if(bv.width() >= bv.height() && bv.width() >= bv.depth())
158  axis = 0;
159  else if(bv.height() >= bv.width() && bv.height() >= bv.depth())
160  axis = 1;
161 
162  splitter.split_axis = axis;
163  S sum = 0;
164 
165  if(splitter.type == BVH_MODEL_TRIANGLES)
166  {
167  for(int i = 0; i < num_primitives; ++i)
168  {
169  const Triangle& t = splitter.tri_indices[primitive_indices[i]];
170  sum += splitter.vertices[t[0]][splitter.split_axis]
171  + splitter.vertices[t[1]][splitter.split_axis]
172  + splitter.vertices[t[2]][splitter.split_axis];
173  }
174 
175  sum /= 3;
176  }
177  else if(splitter.type == BVH_MODEL_POINTCLOUD)
178  {
179  for(int i = 0; i < num_primitives; ++i)
180  {
181  sum += splitter.vertices[primitive_indices[i]][splitter.split_axis];
182  }
183  }
184 
185  splitter.split_value = sum / num_primitives;
186  }
187 };
188 
189 //==============================================================================
190 template <typename BV>
192  const BV& bv, unsigned int* primitive_indices, int num_primitives)
193 {
195  *this, bv, primitive_indices, num_primitives);
196 }
197 
198 //==============================================================================
199 template <typename S, typename BV>
201 {
202  static void run(
203  BVSplitter<BV>& splitter,
204  const BV& bv,
205  unsigned int* primitive_indices,
206  int num_primitives)
207  {
208  int axis = 2;
209 
210  if(bv.width() >= bv.height() && bv.width() >= bv.depth())
211  axis = 0;
212  else if(bv.height() >= bv.width() && bv.height() >= bv.depth())
213  axis = 1;
214 
215  splitter.split_axis = axis;
216  std::vector<S> proj(num_primitives);
217 
218  if(splitter.type == BVH_MODEL_TRIANGLES)
219  {
220  for(int i = 0; i < num_primitives; ++i)
221  {
222  const Triangle& t = splitter.tri_indices[primitive_indices[i]];
223  proj[i] = (splitter.vertices[t[0]][splitter.split_axis]
224  + splitter.vertices[t[1]][splitter.split_axis]
225  + splitter.vertices[t[2]][splitter.split_axis]) / 3;
226  }
227  }
228  else if(splitter.type == BVH_MODEL_POINTCLOUD)
229  {
230  for(int i = 0; i < num_primitives; ++i)
231  proj[i] = splitter.vertices[primitive_indices[i]][splitter.split_axis];
232  }
233 
234  std::sort(proj.begin(), proj.end());
235 
236  if(num_primitives % 2 == 1)
237  {
238  splitter.split_value = proj[(num_primitives - 1) / 2];
239  }
240  else
241  {
242  splitter.split_value = (proj[num_primitives / 2] + proj[num_primitives / 2 - 1]) / 2;
243  }
244  }
245 };
246 
247 //==============================================================================
248 template <typename BV>
250  const BV& bv, unsigned int* primitive_indices, int num_primitives)
251 {
253  *this, bv, primitive_indices, num_primitives);
254 }
255 
256 //==============================================================================
257 template <typename S>
259 {
260  static void run(
261  BVSplitter<OBB<S>>& splitter,
262  const OBB<S>& bv,
263  unsigned int* /*primitive_indices*/,
264  int /*num_primitives*/)
265  {
266  computeSplitVector<S, OBB<S>>(bv, splitter.split_vector);
267  computeSplitValue_bvcenter<S, OBB<S>>(bv, splitter.split_value);
268  }
269 };
270 
271 //==============================================================================
272 template <typename S>
274 {
275  static void run(
276  BVSplitter<OBB<S>>& splitter,
277  const OBB<S>& bv,
278  unsigned int* primitive_indices,
279  int num_primitives)
280  {
281  computeSplitVector<S, OBB<S>>(bv, splitter.split_vector);
282  computeSplitValue_mean<S, OBB<S>>(
283  bv, splitter.vertices, splitter.tri_indices, primitive_indices,
284  num_primitives, splitter.type, splitter.split_vector, splitter.split_value);
285  }
286 };
287 
288 //==============================================================================
289 template <typename S>
291 {
292  static void run(
293  BVSplitter<OBB<S>>& splitter,
294  const OBB<S>& bv,
295  unsigned int* primitive_indices,
296  int num_primitives)
297  {
298  computeSplitVector<S, OBB<S>>(bv, splitter.split_vector);
299  computeSplitValue_median<S, OBB<S>>(
300  bv, splitter.vertices, splitter.tri_indices, primitive_indices,
301  num_primitives, splitter.type, splitter.split_vector, splitter.split_value);
302  }
303 };
304 
305 //==============================================================================
306 template <typename S>
308 {
309  static void run(
310  BVSplitter<RSS<S>>& splitter,
311  const RSS<S>& bv,
312  unsigned int* /*primitive_indices*/,
313  int /*num_primitives*/)
314  {
315  computeSplitVector<S, RSS<S>>(bv, splitter.split_vector);
316  computeSplitValue_bvcenter<S, RSS<S>>(bv, splitter.split_value);
317  }
318 };
319 
320 //==============================================================================
321 template <typename S>
323 {
324  static void run(
325  BVSplitter<RSS<S>>& splitter,
326  const RSS<S>& bv,
327  unsigned int* primitive_indices,
328  int num_primitives)
329  {
330  computeSplitVector<S, RSS<S>>(bv, splitter.split_vector);
331  computeSplitValue_mean<S, RSS<S>>(
332  bv, splitter.vertices, splitter.tri_indices, primitive_indices,
333  num_primitives, splitter.type, splitter.split_vector, splitter.split_value);
334  }
335 };
336 
337 //==============================================================================
338 template <typename S>
340 {
341  static void run(
342  BVSplitter<RSS<S>>& splitter,
343  const RSS<S>& bv,
344  unsigned int* primitive_indices,
345  int num_primitives)
346  {
347  computeSplitVector<S, RSS<S>>(bv, splitter.split_vector);
348  computeSplitValue_median<S, RSS<S>>(
349  bv, splitter.vertices, splitter.tri_indices, primitive_indices,
350  num_primitives, splitter.type, splitter.split_vector, splitter.split_value);
351  }
352 };
353 
354 //==============================================================================
355 template <typename S>
357 {
358  static void run(
359  BVSplitter<kIOS<S>>& splitter,
360  const kIOS<S>& bv,
361  unsigned int* /*primitive_indices*/,
362  int /*num_primitives*/)
363  {
364  computeSplitVector<S, kIOS<S>>(bv, splitter.split_vector);
365  computeSplitValue_bvcenter<S, kIOS<S>>(bv, splitter.split_value);
366  }
367 };
368 
369 //==============================================================================
370 template <typename S>
372 {
373  static void run(
374  BVSplitter<kIOS<S>>& splitter,
375  const kIOS<S>& bv,
376  unsigned int* primitive_indices,
377  int num_primitives)
378  {
379  computeSplitVector<S, kIOS<S>>(bv, splitter.split_vector);
380  computeSplitValue_mean<S, kIOS<S>>(
381  bv, splitter.vertices, splitter.tri_indices, primitive_indices,
382  num_primitives, splitter.type, splitter.split_vector, splitter.split_value);
383  }
384 };
385 
386 //==============================================================================
387 template <typename S>
389 {
390  static void run(
391  BVSplitter<kIOS<S>>& splitter,
392  const kIOS<S>& bv,
393  unsigned int* primitive_indices,
394  int num_primitives)
395  {
396  computeSplitVector<S, kIOS<S>>(bv, splitter.split_vector);
397  computeSplitValue_median<S, kIOS<S>>(
398  bv, splitter.vertices, splitter.tri_indices, primitive_indices,
399  num_primitives, splitter.type, splitter.split_vector, splitter.split_value);
400  }
401 };
402 
403 //==============================================================================
404 template <typename S>
406 {
407  static void run(
408  BVSplitter<OBBRSS<S>>& splitter,
409  const OBBRSS<S>& bv,
410  unsigned int* /*primitive_indices*/,
411  int /*num_primitives*/)
412  {
413  computeSplitVector<S, OBBRSS<S>>(bv, splitter.split_vector);
414  computeSplitValue_bvcenter<S, OBBRSS<S>>(bv, splitter.split_value);
415  }
416 };
417 
418 //==============================================================================
419 template <typename S>
421 {
422  static void run(
423  BVSplitter<OBBRSS<S>>& splitter,
424  const OBBRSS<S>& bv,
425  unsigned int* primitive_indices,
426  int num_primitives)
427  {
428  computeSplitVector<S, OBBRSS<S>>(bv, splitter.split_vector);
429  computeSplitValue_mean<S, OBBRSS<S>>(
430  bv, splitter.vertices, splitter.tri_indices, primitive_indices,
431  num_primitives, splitter.type, splitter.split_vector, splitter.split_value);
432  }
433 };
434 
435 //==============================================================================
436 template <typename S>
438 {
439  static void run(
440  BVSplitter<OBBRSS<S>>& splitter,
441  const OBBRSS<S>& bv,
442  unsigned int* primitive_indices,
443  int num_primitives)
444  {
445  computeSplitVector<S, OBBRSS<S>>(bv, splitter.split_vector);
446  computeSplitValue_median<S, OBBRSS<S>>(
447  bv, splitter.vertices, splitter.tri_indices, primitive_indices,
448  num_primitives, splitter.type, splitter.split_vector, splitter.split_value);
449  }
450 };
451 
452 //==============================================================================
453 template <typename S>
454 struct ApplyImpl<S, OBB<S>>
455 {
456  static bool run(
457  const BVSplitter<OBB<S>>& splitter,
458  const Vector3<S>& q)
459  {
460  return splitter.split_vector.dot(q) > splitter.split_value;
461  }
462 };
463 
464 //==============================================================================
465 template <typename S>
466 struct ApplyImpl<S, RSS<S>>
467 {
468  static bool run(
469  const BVSplitter<RSS<S>>& splitter,
470  const Vector3<S>& q)
471  {
472  return splitter.split_vector.dot(q) > splitter.split_value;
473  }
474 };
475 
476 //==============================================================================
477 template <typename S>
478 struct ApplyImpl<S, kIOS<S>>
479 {
480  static bool run(
481  const BVSplitter<kIOS<S>>& splitter,
482  const Vector3<S>& q)
483  {
484  return splitter.split_vector.dot(q) > splitter.split_value;
485  }
486 };
487 
488 //==============================================================================
489 template <typename S>
490 struct ApplyImpl<S, OBBRSS<S>>
491 {
492  static bool run(
493  const BVSplitter<OBBRSS<S>>& splitter,
494  const Vector3<S>& q)
495  {
496  return splitter.split_vector.dot(q) > splitter.split_value;
497  }
498 };
499 
500 //==============================================================================
501 template <typename BV>
503 {
504  vertices = nullptr;
505  tri_indices = nullptr;
506  type = BVH_MODEL_UNKNOWN;
507 }
508 
509 //==============================================================================
510 template <typename S, typename BV>
512 {
513  static void run(const BV& bv, Vector3<S>& split_vector)
514  {
515  split_vector = bv.axis.col(0);
516  }
517 };
518 
519 //==============================================================================
520 template <typename S, typename BV>
521 void computeSplitVector(const BV& bv, Vector3<S>& split_vector)
522 {
523  ComputeSplitVectorImpl<S, BV>::run(bv, split_vector);
524 }
525 
526 //==============================================================================
527 template <typename S>
529 {
530  static void run(const kIOS<S>& bv, Vector3<S>& split_vector)
531  {
532  /*
533  switch(bv.num_spheres)
534  {
535  case 1:
536  split_vector = Vector3<S>(1, 0, 0);
537  break;
538  case 3:
539  {
540  Vector3<S> v[3];
541  v[0] = bv.spheres[1].o - bv.spheres[0].o;
542  v[0].normalize();
543  generateCoordinateSystem(v[0], v[1], v[2]);
544  split_vector = v[1];
545  }
546  break;
547  case 5:
548  {
549  Vector3<S> v[2];
550  v[0] = bv.spheres[1].o - bv.spheres[0].o;
551  v[1] = bv.spheres[3].o - bv.spheres[0].o;
552  split_vector = v[0].cross(v[1]);
553  split_vector.normalize();
554  }
555  break;
556  default:
557  ;
558  }
559  */
560  split_vector = bv.obb.axis.col(0);
561  }
562 };
563 
564 //==============================================================================
565 template <typename S>
567 {
568  static void run(const OBBRSS<S>& bv, Vector3<S>& split_vector)
569  {
570  split_vector = bv.obb.axis.col(0);
571  }
572 };
573 
574 //==============================================================================
575 template <typename S, typename BV>
576 void computeSplitValue_bvcenter(const BV& bv, S& split_value)
577 {
578  Vector3<S> center = bv.center();
579  split_value = center[0];
580 }
581 
582 //==============================================================================
583 template <typename S, typename BV>
584 void computeSplitValue_mean(
585  const BV& bv,
586  Vector3<S>* vertices,
587  Triangle* triangles,
588  unsigned int* primitive_indices,
589  int num_primitives,
590  BVHModelType type,
591  const Vector3<S>& split_vector,
592  S& split_value)
593 {
594  S sum = 0.0;
595  if(type == BVH_MODEL_TRIANGLES)
596  {
597  S c[3] = {0.0, 0.0, 0.0};
598 
599  for(int i = 0; i < num_primitives; ++i)
600  {
601  const Triangle& t = triangles[primitive_indices[i]];
602  const Vector3<S>& p1 = vertices[t[0]];
603  const Vector3<S>& p2 = vertices[t[1]];
604  const Vector3<S>& p3 = vertices[t[2]];
605 
606  c[0] += (p1[0] + p2[0] + p3[0]);
607  c[1] += (p1[1] + p2[1] + p3[1]);
608  c[2] += (p1[2] + p2[2] + p3[2]);
609  }
610  split_value = (c[0] * split_vector[0] + c[1] * split_vector[1] + c[2] * split_vector[2]) / (3 * num_primitives);
611  }
612  else if(type == BVH_MODEL_POINTCLOUD)
613  {
614  for(int i = 0; i < num_primitives; ++i)
615  {
616  const Vector3<S>& p = vertices[primitive_indices[i]];
617  Vector3<S> v(p[0], p[1], p[2]);
618  sum += v.dot(split_vector);
619  }
620 
621  split_value = sum / num_primitives;
622  }
623 }
624 
625 //==============================================================================
626 template <typename S, typename BV>
627 void computeSplitValue_median(
628  const BV& bv,
629  Vector3<S>* vertices,
630  Triangle* triangles,
631  unsigned int* primitive_indices,
632  int num_primitives,
633  BVHModelType type,
634  const Vector3<S>& split_vector,
635  S& split_value)
636 {
637  std::vector<S> proj(num_primitives);
638 
639  if(type == BVH_MODEL_TRIANGLES)
640  {
641  for(int i = 0; i < num_primitives; ++i)
642  {
643  const Triangle& t = triangles[primitive_indices[i]];
644  const Vector3<S>& p1 = vertices[t[0]];
645  const Vector3<S>& p2 = vertices[t[1]];
646  const Vector3<S>& p3 = vertices[t[2]];
647  Vector3<S> centroid3(p1[0] + p2[0] + p3[0],
648  p1[1] + p2[1] + p3[1],
649  p1[2] + p2[2] + p3[2]);
650 
651  proj[i] = centroid3.dot(split_vector) / 3;
652  }
653  }
654  else if(type == BVH_MODEL_POINTCLOUD)
655  {
656  for(int i = 0; i < num_primitives; ++i)
657  {
658  const Vector3<S>& p = vertices[primitive_indices[i]];
659  Vector3<S> v(p[0], p[1], p[2]);
660  proj[i] = v.dot(split_vector);
661  }
662  }
663 
664  std::sort(proj.begin(), proj.end());
665 
666  if(num_primitives % 2 == 1)
667  {
668  split_value = proj[(num_primitives - 1) / 2];
669  }
670  else
671  {
672  split_value = (proj[num_primitives / 2] + proj[num_primitives / 2 - 1]) / 2;
673  }
674 }
675 
676 } // namespace detail
677 } // namespace fcl
678 
679 #endif
void set(Vector3< S > *vertices_, Triangle *tri_indices_, BVHModelType type_)
Set the geometry data needed by the split rule.
Definition: BV_splitter-inl.h:66
Main namespace.
Definition: broadphase_bruteforce-inl.h:45
triangle model
Definition: BVH_internal.h:79
A class for rectangle sphere-swept bounding volume.
Definition: RSS.h:49
BVHModelType
BVH model type.
Definition: BVH_internal.h:75
virtual ~BVSplitter()
Default deconstructor.
Definition: BV_splitter-inl.h:59
void clear()
Clear the geometry data set before.
Definition: BV_splitter-inl.h:502
Definition: BV_splitter-inl.h:200
Triangle with 3 indices for points.
Definition: triangle.h:47
bool apply(const Vector3< S > &q) const
Apply the split rule on a given point.
Definition: BV_splitter-inl.h:108
unknown model type
Definition: BVH_internal.h:78
OBB< S > obb
OBB member, for rotation.
Definition: OBBRSS.h:57
OBB< S > obb
OBB related with kIOS.
Definition: kIOS.h:72
void computeRule(const BV &bv, unsigned int *primitive_indices, int num_primitives)
Compute the split rule according to a subset of geometry and the corresponding BV node...
Definition: BV_splitter-inl.h:76
Matrix3< S > axis
Orientation of OBB. The axes of the rotation matrix are the principle directions of the box...
Definition: OBB.h:62
Definition: BV_splitter-inl.h:97
Definition: BV_splitter-inl.h:147
A class describing the split rule that splits each BV node.
Definition: BV_splitter.h:65
Definition: BV_splitter-inl.h:115
Class merging the OBB and RSS, can handle collision and distance simultaneously.
Definition: OBBRSS.h:50
Definition: BV_splitter-inl.h:511
A class describing the kIOS collision structure, which is a set of spheres.
Definition: kIOS.h:48
Oriented bounding box class.
Definition: OBB.h:51