Developer Documentation
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
BSPImplT.cc
1 /*===========================================================================*\
2 * *
3 * OpenFlipper *
4  * Copyright (c) 2001-2015, RWTH-Aachen University *
5  * Department of Computer Graphics and Multimedia *
6  * All rights reserved. *
7  * www.openflipper.org *
8  * *
9  *---------------------------------------------------------------------------*
10  * This file is part of OpenFlipper. *
11  *---------------------------------------------------------------------------*
12  * *
13  * Redistribution and use in source and binary forms, with or without *
14  * modification, are permitted provided that the following conditions *
15  * are met: *
16  * *
17  * 1. Redistributions of source code must retain the above copyright notice, *
18  * this list of conditions and the following disclaimer. *
19  * *
20  * 2. Redistributions in binary form must reproduce the above copyright *
21  * notice, this list of conditions and the following disclaimer in the *
22  * documentation and/or other materials provided with the distribution. *
23  * *
24  * 3. Neither the name of the copyright holder nor the names of its *
25  * contributors may be used to endorse or promote products derived from *
26  * this software without specific prior written permission. *
27  * *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39 * *
40 \*===========================================================================*/
41 
42 /*===========================================================================*\
43 * *
44 * $Revision: 10745 $ *
45 * $LastChangedBy: moebius $ *
46 * $Date: 2011-01-26 10:23:50 +0100 (Wed, 26 Jan 2011) $ *
47 * *
48 \*===========================================================================*/
49 
50 
51 
52 
53 //=============================================================================
54 //
55 // CLASS BSPImplT
56 //
57 //=============================================================================
58 
59 #define BSPIMPLT_C
60 
61 //== INCLUDES =================================================================
62 
63 
64 #include "BSPImplT.hh"
65 #include <cfloat>
66 #include <cmath>
67 
68 //== CLASS DEFINITION =========================================================
69 #include <vector>
70 #include <stdexcept>
71 #include <limits>
72 
73 template <class BSPCore>
76 nearest(const Point& _p) const
77 {
79  data.ref = _p;
80  data.dist = infinity_;
81  if (this->root_ == 0)
82  throw std::runtime_error("It seems like the BSP hasn't been built, yet. Did you call build(...)?");
83  _nearest(this->root_, data);
84  return NearestNeighbor(data.nearest, sqrt(data.dist));
85 }
86 
87 
88 //-----------------------------------------------------------------------------
89 
90 
91 template <class BSPCore>
92 void
94 _nearest(Node* _node, NearestNeighborData& _data) const
95 {
96  // terminal node
97  if (!_node->left_child_)
98  {
99  Scalar dist(0);
100  for (HandleIter it=_node->begin(); it!=_node->end(); ++it)
101  {
102  dist = this->traits_.sqrdist(*it, _data.ref);
103  if (dist < _data.dist)
104  {
105  _data.dist = dist;
106  _data.nearest = *it;
107  }
108  }
109  }
110 
111  // non-terminal node
112  else
113  {
114  Scalar dist = _node->plane_.distance(_data.ref);
115  if (dist > 0.0)
116  {
117  _nearest(_node->left_child_, _data);
118  if (dist*dist < _data.dist)
119  _nearest(_node->right_child_, _data);
120  }
121  else
122  {
123  _nearest(_node->right_child_, _data);
124  if (dist*dist < _data.dist)
125  _nearest(_node->left_child_, _data);
126  }
127  }
128 }
129 
130 //-----------------------------------------------------------------------------
131 
132 template <class BSPCore>
135 raycollision(const Point& _p, const Point& _r) const
136 {
137  // Prepare the struct for returning the data
138  RayCollisionData data;
139  data.ref = _p;
140  data.ray = _r;
141  data.hit_handles.clear();
142 
143  _raycollision_non_directional(this->root_, data);
144 
145  std::sort(data.hit_handles.begin(), data.hit_handles.end(), less_pair_second<Handle,Scalar>());
146  return RayCollision(data.hit_handles);
147 }
148 
149 template <class BSPCore>
152 directionalRaycollision(const Point& _p, const Point& _r) const {
153 
154  // Prepare the struct for returning the data
155  RayCollisionData data;
156  data.ref = _p;
157  data.ray = _r;
158  data.hit_handles.clear();
159 
160  _raycollision_directional(this->root_, data);
161 
162  std::sort(data.hit_handles.begin(), data.hit_handles.end(), less_pair_second<Handle,Scalar>());
163  return RayCollision(data.hit_handles);
164 
165 }
166 
167 template <class BSPCore>
170 nearestRaycollision(const Point& _p, const Point& _r) const {
171 
172  // Prepare the struct for returning the data
173  RayCollisionData data;
174  data.ref = _p;
175  data.ray = _r;
176  data.hit_handles.clear();
177 
178  _raycollision_nearest_directional(this->root_, data);
179 
180  return RayCollision(data.hit_handles);
181 }
182 
183 template<class BSPCore>
184 template<class Callback>
185 void
187 intersectBall(const Point &_c, Scalar _r, Callback _callback) const
188 {
189  _intersect_ball(*(this->root_), _c, _r, _callback);
190 }
191 
192 
193 //-----------------------------------------------------------------------------
194 
195 
196 template <class BSPCore>
197 void
200 {
201  // terminal node
202  if (!_node->left_child_)
203  {
204  Scalar dist;
205  Point v0, v1, v2;
206  Scalar u, v;
207 
208  for (HandleIter it=_node->begin(); it!=_node->end(); ++it)
209  {
210  this->traits_.points(*it, v0, v1, v2);
211  if (ACG::Geometry::triangleIntersection(_data.ref, _data.ray, v0, v1, v2, dist, u, v)) {
212  // face intersects with ray.
213  _data.hit_handles.push_back(std::pair<Handle,Scalar>(*it,dist));
214  }
215  }
216  }
217 
218  // non-terminal node
219  else
220  {
221  Scalar tmin, tmax;
222  if ( _node->left_child_ && ACG::Geometry::axisAlignedBBIntersection( _data.ref, _data.ray, _node->left_child_->bb_min, _node->left_child_->bb_max, tmin, tmax)) {
223  _raycollision_non_directional(_node->left_child_, _data);
224  }
225  if ( _node->right_child_ && ACG::Geometry::axisAlignedBBIntersection( _data.ref, _data.ray, _node->right_child_->bb_min, _node->right_child_->bb_max, tmin, tmax)) {
226  _raycollision_non_directional(_node->right_child_, _data);
227  }
228  }
229 }
230 
231 //-----------------------------------------------------------------------------
232 
233 
234 template <class BSPCore>
235 void
237 _raycollision_directional(Node* _node, RayCollisionData& _data) const
238 {
239  // terminal node
240  if (!_node->left_child_)
241  {
242  Scalar dist;
243  Point v0, v1, v2;
244  Scalar u, v;
245 
246  for (HandleIter it=_node->begin(); it!=_node->end(); ++it)
247  {
248  this->traits_.points(*it, v0, v1, v2);
249  if (ACG::Geometry::triangleIntersection(_data.ref, _data.ray, v0, v1, v2, dist, u, v)) {
250  if (dist > 0.0){
251  _data.hit_handles.push_back(std::pair<Handle,Scalar>(*it,dist));
252  }
253  }
254  }
255  }
256 
257  // non-terminal node
258  else
259  {
260  Scalar tmin, tmax;
261  if ( _node->left_child_ && ACG::Geometry::axisAlignedBBIntersection( _data.ref, _data.ray, _node->left_child_->bb_min, _node->left_child_->bb_max, tmin, tmax)) {
262  _raycollision_directional(_node->left_child_, _data);
263  }
264  if ( _node->right_child_ && ACG::Geometry::axisAlignedBBIntersection( _data.ref, _data.ray, _node->right_child_->bb_min, _node->right_child_->bb_max, tmin, tmax)) {
265  _raycollision_directional(_node->right_child_, _data);
266  }
267  }
268 }
269 
270 //-----------------------------------------------------------------------------
271 
272 
273 template <class BSPCore>
274 void
276 _raycollision_nearest_directional(Node* _node, RayCollisionData& _data) const
277 {
278  // terminal node
279  if (!_node->left_child_)
280  {
281  Scalar dist;
282  Point v0, v1, v2;
283  Scalar u, v;
284 
285  for (HandleIter it=_node->begin(); it!=_node->end(); ++it)
286  {
287  this->traits_.points(*it, v0, v1, v2);
288  if (ACG::Geometry::triangleIntersection(_data.ref, _data.ray, v0, v1, v2, dist, u, v)) {
289  if (dist > 0.0){
290  _data.hit_handles.push_back(std::pair<Handle,Scalar>(*it, dist));
291  }
292  }
293  }
294  // only return the closest hit
295  if(!_data.hit_handles.empty()) {
296  std::partial_sort(_data.hit_handles.begin(), _data.hit_handles.begin() + 1, _data.hit_handles.end(), less_pair_second<Handle, Scalar>());
297  _data.hit_handles.resize(1);
298  }
299  }
300 
301  // non-terminal node
302  else
303  {
304  // determine order of traversal
305  Node* first_node = _node->left_child_, *second_node = _node->right_child_;
306  if (!_node->plane_(_data.ref)) {
307  std::swap(first_node, second_node);
308  }
309 
310  Scalar tmin, tmax;
311  if ( first_node && ACG::Geometry::axisAlignedBBIntersection( _data.ref, _data.ray, first_node->bb_min, first_node->bb_max, tmin, tmax) ) {
312  _raycollision_nearest_directional(first_node, _data);
313  }
314  // if the second node is further away than the closeset hit skip it
315  Scalar dist = ACG::NumLimitsT<Scalar>::max();
316  if(!_data.hit_handles.empty()) {
317  dist = _data.hit_handles.front().second;
318  }
319  if ( second_node && ACG::Geometry::axisAlignedBBIntersection( _data.ref, _data.ray, second_node->bb_min, second_node->bb_max, tmin, tmax) && (tmin < dist) ) {
320  _raycollision_nearest_directional(second_node, _data);
321  }
322  }
323 }
324 template<class BSPCore>
325 template<class Callback>
327 _intersect_ball(const Node &_node,
328  const Point &_c,
329  Scalar _r,
330  Callback _callback) const
331 {
332  // terminal node
333  if (!_node.left_child_)
334  {
335  const double r_sqr = _r * _r;
336  for (const auto &fh: _node) {
337  const double dist = this->traits_.sqrdist(fh, _c);
338  if (dist < r_sqr) {
339  _callback(fh);
340  }
341  }
342  }
343  else // non-terminal node
344  {
345  const Scalar dist = _node.plane_.distance(_c);
346  const Node &left = *_node.left_child_;
347  const Node &right = *_node.right_child_;
348 
349  if (dist > -_r){
350  _intersect_ball(left, _c, _r, _callback);
351  }
352  if (dist < _r) {
353  _intersect_ball(right, _c, _r, _callback);
354  }
355  }
356 }
357 
358 
359 //=============================================================================
360 
RayCollision raycollision(const Point &_p, const Point &_r) const
intersect mesh with ray
Definition: BSPImplT.cc:135
static Scalar max()
Return the maximum absolte value a scalar type can store.
Definition: NumLimitsT.hh:104
void intersectBall(const Point &_c, Scalar _r, Callback _callback) const
intersect mesh with open ball
Definition: BSPImplT.cc:187
bool triangleIntersection(const Vec &_o, const Vec &_dir, const Vec &_v0, const Vec &_v1, const Vec &_v2, typename Vec::value_type &_t, typename Vec::value_type &_u, typename Vec::value_type &_v)
Intersect a ray and a triangle.
Definition: Algorithms.cc:1317
std::vector< std::pair< Handle, Scalar > > RayCollision
Store nearest neighbor information.
Definition: BSPImplT.hh:105
NearestNeighbor nearest(const Point &_p) const
Return handle of the nearest neighbor face.
Definition: BSPImplT.cc:76
Store nearest neighbor information.
Definition: BSPImplT.hh:167
Store ray collide information.
Definition: BSPImplT.hh:180
Store nearest neighbor information.
Definition: BSPImplT.hh:96
bool axisAlignedBBIntersection(const Vec &_o, const Vec &_dir, const Vec &_bbmin, const Vec &_bbmax, typename Vec::value_type &tmin, typename Vec::value_type &tmax)
Intersect a ray and an axis aligned bounding box.
Definition: Algorithms.cc:1367
void _raycollision_non_directional(Node *_node, RayCollisionData &_data) const
recursive part of raycollision()
Definition: BSPImplT.cc:199
RayCollision directionalRaycollision(const Point &_p, const Point &_r) const
intersect mesh with ray
Definition: BSPImplT.cc:152
void _raycollision_directional(Node *_node, RayCollisionData &_data) const
recursive part of directionalRaycollision()
Definition: BSPImplT.cc:237
RayCollision nearestRaycollision(const Point &_p, const Point &_r) const
intersect mesh with ray
Definition: BSPImplT.cc:170