1 // Copyright 2006-2009 Brad King, Chuck Stewart
2 // Distributed under the Boost Software License, Version 1.0.
3 // (See accompanying file rgtl_license_1_0.txt or copy at
4 // http://www.boost.org/LICENSE_1_0.txt)
5 #ifndef rgtl_sqt_objects_hxx
6 #define rgtl_sqt_objects_hxx
7
8 #include <limits>
9 #include <iostream>
10 #include <memory>
11 #include <cstdlib>
12 #include <cmath>
13 #ifdef _MSC_VER
14 # include <vcl_msvc_warnings.h>
15 #endif
16 #include "rgtl_sqt_objects.h"
17
18 #include "rgtl_config.h"
19 #include "rgtl_object_array.h"
20 #include "rgtl_object_once.h"
21 #include "rgtl_octree_data_fixed.hxx"
22 #include "rgtl_sqt_cell_bounds.h"
23 #include "rgtl_sqt_cell_geometry.h"
24 #include "rgtl_sqt_cell_location.h"
25 #include "rgtl_sqt_object_array.h"
26 #include "rgtl_sqt_space.hxx"
27 #include "rgtl_serialize_access.h"
28 #include "rgtl_serialize_base.h"
29 #include "rgtl_serialize_vnl_vector_fixed.h"
30 #include "rgtl_serialize_istream.h"
31 #include "rgtl_serialize_ostream.h"
32
33 #include <vnl/vnl_math.h>
34 #include <vnl/vnl_vector_fixed.h>
35
36 #include <cassert>
37
38 // TODO: During tree construction we should check the set of objects
39 // in the current node. Those with no boundary inside the node should
40 // be left out of the count of objects remaining because no amount of
41 // subdivision will reduce the count.
42
43 //#define RGTL_SQT_OBJECTS_DEBUG_BUILD
44 //#define RGTL_SQT_OBJECTS_DEBUG_BUILD2
45 //#define RGTL_SQT_OBJECTS_DEBUG_QUERY
46
47 #if defined(RGTL_SQT_OBJECTS_DEBUG_BUILD) || \
48 defined(RGTL_SQT_OBJECTS_DEBUG_BUILD2) || \
49 defined(RGTL_SQT_OBJECTS_DEBUG_QUERY) || 0
50 # include <std::iostream.h>
51 # include <std::exception.h>
52 #endif
53
54 //----------------------------------------------------------------------------
55 // All cells store bounding information.
56 template <unsigned int D>
57 struct rgtl_sqt_objects_cell_data
58 {
59 typedef float cone_bounds_type;
60 cone_bounds_type depth_min;
61 cone_bounds_type depth_max;
62 cone_bounds_type cone_axis[D];
63 cone_bounds_type cone_angle;
64 private:
65 friend class rgtl_serialize_access;
66 template <class Serializer>
serializergtl_sqt_objects_cell_data67 void serialize(Serializer& sr)
68 {
69 sr & depth_min;
70 sr & depth_max;
71 sr & cone_axis;
72 sr & cone_angle;
73 }
74 };
75
76 // Leaves hold per-cell information and also store objects.
77 template <unsigned int D>
78 struct rgtl_sqt_objects_leaf_data: public rgtl_sqt_objects_cell_data<D>
79 {
80 typedef rgtl_sqt_objects_cell_data<D> derived;
81 typedef int index_type;
82
83 // Store the begin and end index into a list of object ids
84 // associated with the tree in which this leaf is stored.
85 index_type index_begin;
86 index_type index_end;
87
rgtl_sqt_objects_leaf_datargtl_sqt_objects_leaf_data88 rgtl_sqt_objects_leaf_data() {}
rgtl_sqt_objects_leaf_datargtl_sqt_objects_leaf_data89 rgtl_sqt_objects_leaf_data(index_type begin, index_type end):
90 index_begin(begin), index_end(end) {}
91 private:
92 friend class rgtl_serialize_access;
93 template <class Serializer>
serializergtl_sqt_objects_leaf_data94 void serialize(Serializer& sr)
95 {
96 sr & rgtl_serialize_base<derived>(*this);
97 sr & index_begin;
98 sr & index_end;
99 }
100 };
101
102 // Nodes hold per-cell information.
103 template <unsigned int D>
104 struct rgtl_sqt_objects_node_data: public rgtl_sqt_objects_cell_data<D>
105 {
106 typedef rgtl_sqt_objects_cell_data<D> derived;
107 private:
108 friend class rgtl_serialize_access;
109 template <class Serializer>
serializergtl_sqt_objects_node_data110 void serialize(Serializer& sr)
111 {
112 sr & rgtl_serialize_base<derived>(*this);
113 }
114 };
115
116 //----------------------------------------------------------------------------
117 // Method helper object forward declarations.
118 template <unsigned int D> class rgtl_sqt_objects_query_closest;
119 template <unsigned int D, unsigned int Face>
120 class rgtl_sqt_objects_query_closest_face;
121
122 //----------------------------------------------------------------------------
123 // Superclass for typed per-face implementation of spatial structure.
124 template <unsigned int D>
125 class rgtl_sqt_objects_face_base
126 {
127 public:
128 // Type stored in tree leaves.
129 typedef rgtl_sqt_objects_leaf_data<D> leaf_data_type;
130
131 // Type stored in tree nodes.
132 typedef rgtl_sqt_objects_node_data<D> node_data_type;
133
134 // The type of the quad-tree itself.
135 typedef rgtl_octree_data_fixed<D-1,
136 leaf_data_type, node_data_type> tree_type;
137
138 // Type-safe cell index in quad-tree representation.
139 typedef typename tree_type::cell_index_type cell_index_type;
140
141 // Type-safe child index in quad-tree representation.
142 typedef typename tree_type::child_index_type child_index_type;
143
144 // Type of logical SQT cell location.
145 typedef rgtl_sqt_cell_location<D> cell_location_type;
146
147 // Type representing SQT cell parameter bounds.
148 typedef rgtl_sqt_cell_bounds<D> cell_bounds_type;
149
150 // Full spatial structure internal representation type.
151 typedef rgtl_sqt_objects_internal<D> internal_type;
152
153 // Type representing the original array of objects stored.
154 typedef typename internal_type::object_array_type object_array_type;
155
156 // Type of pointer to set of objects during construction.
157 typedef std::unique_ptr< rgtl_sqt_object_set<D> > sqt_object_set_ptr;
158
159 // Construct with reference to main internal representation.
rgtl_sqt_objects_face_base(internal_type & intern)160 rgtl_sqt_objects_face_base(internal_type& intern): internal_(intern) {}
161
162 // Build the spatial structure in this face.
163 virtual void build(sqt_object_set_ptr&) = 0;
164
165 // Convert a direction in this face to parameters.
166 virtual void direction_to_parameters(double const d[D],
167 double u[D-1]) const = 0;
168
169 // Query a ray contained in this face.
170 virtual bool query_ray(double const d[D], double x[D], double* s) const = 0;
171
172 virtual void query_closest(double const p[D], int k, double const u[D-1],
173 rgtl_sqt_objects_query_closest<D>& qc) const = 0;
174
175 // Access the tree representation for this face.
tree()176 tree_type& tree() { return this->tree_; }
tree() const177 tree_type const& tree() const { return this->tree_; }
178
179 protected:
180 // Reference the full spatial structure internal implementation that
181 // owns this face.
182 internal_type& internal_;
183
184 // The actual quad-tree structure for this face.
185 tree_type tree_;
186
187 // Leaf data stores index ranges into this array which maps to the
188 // object ids in each leaf.
189 std::vector<int> object_ids_;
190
191 private:
192 friend class rgtl_serialize_access;
serialize(Serializer & sr)193 template <class Serializer> void serialize(Serializer& sr)
194 {
195 sr & tree_;
196 sr & object_ids_;
197 }
198 };
199
200 // Implementation of spatial structure for a single face.
201 template <unsigned int D, unsigned int Face>
202 class rgtl_sqt_objects_face: public rgtl_sqt_objects_face_base<D>
203 {
204 public:
205 typedef rgtl_sqt_objects_face_base<D> derived;
206
207 // Promote type names from superclass.
208 typedef typename derived::leaf_data_type leaf_data_type;
209 typedef typename derived::node_data_type node_data_type;
210 typedef typename derived::tree_type tree_type;
211 typedef typename derived::cell_index_type cell_index_type;
212 typedef typename derived::child_index_type child_index_type;
213 typedef typename derived::cell_location_type cell_location_type;
214 typedef typename derived::cell_bounds_type cell_bounds_type;
215 typedef typename derived::internal_type internal_type;
216 typedef typename derived::object_array_type object_array_type;
217
218 // Type maintaining SQT cell geometry as the tree is traversed.
219 typedef rgtl_sqt_cell_geometry<D, Face> cell_geometry_type;
220
221 // Construct empty tree with reference to full spatial structure
222 // instance holding this per-face instance.
rgtl_sqt_objects_face(internal_type & intern)223 rgtl_sqt_objects_face(internal_type& intern): derived(intern) {}
224
225 // Pointer type for object set base class.
226 typedef std::unique_ptr< rgtl_sqt_object_set<D> > sqt_object_set_ptr;
227
228 // Pointer type for object set representation in this face.
229 typedef std::unique_ptr< rgtl_sqt_object_set_face<D, Face> >
230 sqt_object_set_face_ptr;
231
232 // Spatial parameterization for this face.
233 typedef rgtl_sqt_space<D, Face> space;
234
235 // Convert a direction in this face to parameters.
direction_to_parameters(double const d[D],double u[D-1]) const236 virtual void direction_to_parameters(double const d[D],
237 double u[D-1]) const
238 {
239 space::direction_to_parameters(d, u);
240 }
241
242 // Build the spatial structure in this face.
243 virtual void build(sqt_object_set_ptr& oa);
244
245 // Query a ray contained in this face.
246 virtual bool query_ray(double const d[D], double x[D], double* s) const;
247
248 virtual void query_closest(double const p[D], int k, double const u[D-1],
249 rgtl_sqt_objects_query_closest<D>& qc) const;
250
251 #ifdef RGTL_SQT_OBJECTS_DEBUG_BUILD2
252 class exception_stack
253 {
254 public:
exception_stack(cell_location_type const & cell)255 exception_stack(cell_location_type const& cell):
256 cell_(cell), msg_(""), sz1_(0) {}
set_message(const char * msg)257 void set_message(const char* msg) { this->msg_ = msg; }
set_size1(unsigned int sz1)258 void set_size1(unsigned int sz1) { this->sz1_ = sz1; }
~exception_stack()259 ~exception_stack()
260 {
261 if (std::uncaught_exception())
262 {
263 std::cerr << " " << cell_ << " (" << this->sz1_
264 << ") " << this->msg_ << '\n';
265 }
266 }
267 private:
268 cell_location_type const& cell_;
269 const char* msg_;
270 unsigned int sz1_;
271 };
272 #endif
273
274 private:
275 // Recursive method to actually build the spatial structure in this face.
276 void build(cell_geometry_type const& cell_geometry,
277 cell_index_type cell_index,
278 sqt_object_set_face_ptr& oa);
279
280 // Recursive implementation of ray query.
281 bool query_ray(cell_location_type const& cell, cell_index_type cell_index,
282 double const u[D-1], double const d[D], double x[D],
283 double* s) const;
284 bool query_ray(int id, double const d[D], double x[D], double* s) const;
285
286 // Access methods for internal representation.
object_array() const287 object_array_type const& object_array() const
288 { return this->internal_.object_array(); }
origin() const289 vnl_vector_fixed<double,D> const& origin() const
290 { return this->internal_.origin(); }
291
292 friend class rgtl_sqt_objects_query_closest_face<D, Face>;
293
294 friend class rgtl_serialize_access;
295 template <class Serializer>
serialize(Serializer & sr)296 void serialize(Serializer& sr)
297 {
298 sr & rgtl_serialize_base<derived>(*this);
299 }
300 };
301
302 //----------------------------------------------------------------------------
303 // Template container to hold a typed object for each face.
304 template <unsigned int D, unsigned int Face> class rgtl_sqt_objects_faces;
305
306 // Base class for face container. Does not hold any faces but is used
307 // to terminate recursive instantiation.
308 template <unsigned int D>
309 class rgtl_sqt_objects_faces_base
310 {
311 public:
rgtl_sqt_objects_faces_base(rgtl_sqt_objects_internal<D> &,rgtl_sqt_objects_face_base<D> * [(D<<1)])312 rgtl_sqt_objects_faces_base(rgtl_sqt_objects_internal<D>&,
313 rgtl_sqt_objects_face_base<D>* [(D<<1)]) {}
314 private:
315 friend class rgtl_serialize_access;
serialize(Serializer &)316 template <class Serializer> void serialize(Serializer&) {}
317 };
318
319 // Template to lookup the next holding type for the next face.
320 template <unsigned int Face> struct rgtl_sqt_objects_face_next
321 {
322 template <unsigned int D>
323 struct get { typedef rgtl_sqt_objects_faces<D, Face-1> type; };
324 };
325
326 template <> struct rgtl_sqt_objects_face_next<0>
327 {
328 template <unsigned int D>
329 struct get { typedef rgtl_sqt_objects_faces_base<D> type; };
330 };
331
332 template <unsigned int D, unsigned int Face>
333 class rgtl_sqt_objects_faces
334 : public rgtl_sqt_objects_face_next<Face>::template get<D>::type
335 {
336 public:
337 // Superclass holds additional faces.
338 typedef typename
339 rgtl_sqt_objects_face_next<Face>::template get<D>::type derived;
340
341 // Construct a face and provide a pointer to it.
rgtl_sqt_objects_faces(rgtl_sqt_objects_internal<D> & intern,rgtl_sqt_objects_face_base<D> * p[(D<<1)])342 rgtl_sqt_objects_faces(rgtl_sqt_objects_internal<D>& intern,
343 rgtl_sqt_objects_face_base<D>* p[(D<<1)])
344 : derived(intern, p), face_(intern)
345 {
346 p[Face] = &face_;
347 }
348 private:
349 // Hold a face instance.
350 rgtl_sqt_objects_face<D, Face> face_;
351
352 friend class rgtl_serialize_access;
353 template <class Serializer>
serialize(Serializer & sr)354 void serialize(Serializer& sr)
355 {
356 sr & rgtl_serialize_base<derived>(*this);
357 sr & face_;
358 }
359 };
360
361 //----------------------------------------------------------------------------
362 template <unsigned int D>
363 class rgtl_sqt_objects_internal
364 {
365 public:
366 // Type holding original array of objects stored.
367 typedef rgtl_object_array<D> object_array_type;
368
369 // Type holding SQT-specific representation of object array.
370 typedef rgtl_sqt_object_array<D> sqt_object_array_type;
371 typedef std::unique_ptr<sqt_object_array_type> sqt_object_array_ptr;
372
373 // Type holding SQT-specific representation of object set during
374 // cell construction.
375 typedef rgtl_sqt_object_set<D> sqt_object_set_type;
376 typedef std::unique_ptr<sqt_object_set_type> sqt_object_set_ptr;
377
378 // Default constructor.
379 rgtl_sqt_objects_internal(object_array_type const& original_objs);
380
381 // Constructor for SQT-specific representation of input object array.
382 void build(sqt_object_array_type const& objs,
383 double const origin[D], int ml, int mpl);
384
385 // Get the implementation object for a given face index.
face(unsigned int i)386 rgtl_sqt_objects_face_base<D>& face(unsigned int i)
387 {
388 return *faces_[i];
389 }
face(unsigned int i) const390 rgtl_sqt_objects_face_base<D> const& face(unsigned int i) const
391 {
392 return *faces_[i];
393 }
394
395 // Get tree building parameters.
max_level() const396 int max_level() const { return this->max_level_; }
max_per_leaf() const397 int max_per_leaf() const { return this->max_per_leaf_; }
398
399 // Get the original object array.
object_array() const400 object_array_type const& object_array() const
401 { return this->object_array_; }
402
403 // Get the SQT guard position. This is also the origin of all sight rays.
origin() const404 vnl_vector_fixed<double,D> const& origin() const { return this->origin_; }
origin(unsigned int a) const405 double origin(unsigned int a) const { return this->origin_[a]; }
406
407 // External interface method implementations.
408 bool query_ray(double const d[D], double x[D], double* s) const;
409 int query_closest(double const p[D], int k, int* ids,
410 double* squared_distances, double* points,
411 double bound_squared) const;
412
number_of_objects() const413 int number_of_objects() const
414 {
415 return this->object_array_.number_of_objects();
416 }
417
object_closest_point(int id,double const x[D],double y[D],double bound_squared) const418 bool object_closest_point(int id,
419 double const x[D],
420 double y[D],
421 double bound_squared) const
422 {
423 return this->object_array_.object_closest_point(id, x, y, bound_squared);
424 }
425
visit_once(int id) const426 bool visit_once(int id) const
427 {
428 return this->object_once_.visit(id);
429 }
430
431 #ifdef RGTL_SQT_OBJECTS_DEBUG_QUERY
set_query_closest_debug(bool b)432 void set_query_closest_debug(bool b) { this->query_closest_debug_ = b; }
433 #else
set_query_closest_debug(bool)434 void set_query_closest_debug(bool) {}
435 #endif
436
437 private:
438 // Container holding typed face instances.
439 rgtl_sqt_objects_faces<D, (D<<1)-1> faces_container_;
440
441 // Array of face instance pointers to allow random access to face
442 // implementations.
443 rgtl_sqt_objects_face_base<D>* faces_[(D<<1)];
444
445 // Reference to set of objects held in spatial structure.
446 object_array_type const& object_array_;
447
448 // Keep track of objects visited on a per-query basis.
449 rgtl_object_once object_once_;
450
451 // The maximum subdivision level.
452 int max_level_;
453
454 // The maximum number of objects per leaf.
455 int max_per_leaf_;
456
457 // The guard location of the star-shaped region.
458 vnl_vector_fixed<double,D> origin_;
459
460 friend class rgtl_sqt_objects_query_closest<D>;
461
462 #ifdef RGTL_SQT_OBJECTS_DEBUG_QUERY
463 public:
464 // Enable closest point query output only after the distance
465 // transform has finished.
466 bool query_closest_debug_;
467 #endif
468
469 friend class rgtl_serialize_access;
470 template <class Serializer>
serialize(Serializer & sr)471 void serialize(Serializer& sr)
472 {
473 sr & faces_container_;
474 sr & object_once_;
475 sr & max_level_;
476 sr & max_per_leaf_;
477 sr & origin_;
478 }
479 };
480
481 //----------------------------------------------------------------------------
482 template <unsigned int D>
483 rgtl_sqt_objects_internal<D>
rgtl_sqt_objects_internal(object_array_type const & original_objs)484 ::rgtl_sqt_objects_internal(object_array_type const& original_objs):
485 faces_container_(*this, faces_),
486 object_array_(original_objs),
487 object_once_(),
488 max_level_(0), max_per_leaf_(0)
489 {
490 }
491
492 //----------------------------------------------------------------------------
493 template <unsigned int D>
build(sqt_object_array_type const & objs,double const origin[D],int ml,int mpl)494 void rgtl_sqt_objects_internal<D>::build(sqt_object_array_type const& objs,
495 double const origin[D],
496 int ml, int mpl)
497 {
498 assert(&this->object_array_ == &objs.original());
499 this->object_once_.set_number_of_objects(
500 this->object_array_.number_of_objects());
501 this->max_level_ = ml;
502 this->max_per_leaf_ = mpl;
503
504 #ifdef RGTL_SQT_OBJECTS_DEBUG_QUERY
505 this->query_closest_debug_ = false;
506 #endif
507
508 for (unsigned int a=0; a < D; ++a)
509 {
510 this->origin_[a] = origin[a];
511 }
512
513 int n = this->number_of_objects();
514 std::vector<int> ids(n);
515 for (int i=0; i < n; ++i)
516 {
517 ids[i] = i;
518 }
519
520 for (unsigned int i=0; i < (D<<1); ++i)
521 {
522 sqt_object_set_ptr soa(objs.new_set(this->origin_.data_block(), i));
523 this->face(i).build(soa);
524 }
525 }
526
527 //----------------------------------------------------------------------------
528 template <unsigned int D>
529 bool
query_ray(double const d[D],double x[D],double * s) const530 rgtl_sqt_objects_internal<D>::query_ray(double const d[D],
531 double x[D], double* s) const
532 {
533 unsigned int f = rgtl_sqt_space_base<D>::direction_to_face(d);
534 return this->face(f).query_ray(d, x, s);
535 }
536
537 //----------------------------------------------------------------------------
538 template <unsigned int D>
539 class rgtl_sqt_objects_query_closest
540 {
541 public:
542 typedef rgtl_sqt_objects_internal<D> internal_type;
rgtl_sqt_objects_query_closest(internal_type const & intern,double const p[D],int k,double bound_squared)543 rgtl_sqt_objects_query_closest(internal_type const& intern,
544 double const p[D], int k,
545 double bound_squared)
546 : internal_(intern), best_(k)
547 {
548 #ifdef RGTL_SQT_OBJECTS_DEBUG_QUERY
549 this->checked_count_ = 0;
550 #endif
551 this->center_depth_squared_ = 0;
552 for (unsigned int a=0; a < D; ++a)
553 {
554 this->center_direction_[a] = p[a] - this->internal_.origin(a);
555 this->center_depth_squared_ +=
556 this->center_direction_[a]*this->center_direction_[a];
557 }
558 this->center_face_ =
559 rgtl_sqt_space_base<D>::direction_to_face(this->center_direction_);
560 this->internal_.face(this->center_face_).direction_to_parameters(
561 this->center_direction_, this->center_parameters_);
562 this->center_depth_ = std::sqrt(this->center_depth_squared_);
563 this->set_bound(bound_squared);
564 #ifdef RGTL_SQT_OBJECTS_DEBUG_QUERY
565 if (this->internal_.query_closest_debug_)
566 {
567 std::cout << "Querying point (";
568 const char* sep = "";
569 for (unsigned int a=0; a < D; ++a)
570 {
571 std::cout << sep << p[a];
572 sep = ", ";
573 }
574 std::cout << ") with initial bound " << this->bound_ << std::endl;
575 }
576 #endif
577 }
578
579 void check_object(double const p[D], int k, int id);
580 int get_result(int k, int* ids, double* squared_distances, double* points);
581
582 // Entry in the list of closest objects.
583 struct closest_object_entry
584 {
closest_object_entryrgtl_sqt_objects_query_closest::closest_object_entry585 closest_object_entry(): id(-1), distance_squared(-1) {}
closest_object_entryrgtl_sqt_objects_query_closest::closest_object_entry586 closest_object_entry(int idx, double d2, double q[D])
587 : id(idx), distance_squared(d2)
588 {
589 for (unsigned int a=0; a < D; ++a)
590 {
591 this->point[a] = q[a];
592 }
593 }
594 int id;
595 double distance_squared;
596 double point[D];
597
operator <rgtl_sqt_objects_query_closest::closest_object_entry598 bool operator<(closest_object_entry const& that)
599 {
600 return this->distance_squared >= 0 &&
601 that.distance_squared >= 0 &&
602 this->distance_squared < that.distance_squared;
603 }
604 };
605
606 void update_bound(double bound);
607 void set_bound(double bound);
608
609 // Compute the squared distance between two points.
compute_distance_squared(double const p[D],double const q[D])610 static double compute_distance_squared(double const p[D],
611 double const q[D])
612 {
613 double d = 0.0;
614 for (unsigned int a=0; a < D; ++a)
615 {
616 double da = p[a]-q[a];
617 d += da*da;
618 }
619 return d;
620 }
621
622 // Compute the distance between two points.
compute_distance(double const p[D],double const q[D])623 static double compute_distance(double const p[D],
624 double const q[D])
625 {
626 return std::sqrt(compute_distance_squared(p, q));
627 }
628
629 // The internal sqt objects representation.
630 internal_type const& internal_;
631
632 // Keep a sorted list of the best k squared distances. Use -1 to
633 // indicate no object yet found.
634 std::vector<closest_object_entry> best_;
635
636 // Keep track of the current squared distance bound.
637 double bound_;
638
639 // The parameters of the query point direction.
640 unsigned int center_face_;
641 double center_parameters_[D-1];
642
643 // Keep track of the current bounding sphere.
644 double center_depth_;
645 double center_depth_squared_;
646 double center_direction_[D];
647 double radius_;
648
649 #ifdef RGTL_SQT_OBJECTS_DEBUG_QUERY
650 // Keep track of the number of object queries made.
651 int checked_count_;
652 #endif
653 };
654
655 //----------------------------------------------------------------------------
656 template <unsigned int D>
657 void
658 rgtl_sqt_objects_query_closest<D>
check_object(double const p[D],int k,int id)659 ::check_object(double const p[D], int k, int id)
660 {
661 #ifdef RGTL_SQT_OBJECTS_DEBUG_QUERY
662 ++this->checked_count_;
663 if (this->internal_.query_closest_debug_)
664 {
665 std::cout << " checking object id " << id << std::endl;
666 }
667 #endif
668 // Get the squared distance to this object and use it only
669 // if it is smaller than the current distance bound.
670 double q[D];
671 double distance_squared;
672 if (this->internal_.object_closest_point(id, p, q, this->bound_) &&
673 (distance_squared = this->compute_distance_squared(p, q),
674 distance_squared <= this->bound_))
675 {
676 // Insert this object into our sorted list of k objects.
677 std::vector<closest_object_entry>& best = this->best_;
678 closest_object_entry obj(id, distance_squared, q);
679 for (int j=0; j < k && obj.distance_squared >= 0; ++j)
680 {
681 if (best[j].distance_squared < 0 || obj < best[j])
682 {
683 std::swap(obj, best[j]);
684 }
685 }
686
687 // Update the current bounding sphere radius.
688 this->update_bound(best[k-1].distance_squared);
689 }
690 }
691
692 //----------------------------------------------------------------------------
693 template <unsigned int D>
694 int
695 rgtl_sqt_objects_query_closest<D>
get_result(int k,int * ids,double * squared_distances,double * points)696 ::get_result(int k, int* ids, double* squared_distances, double* points)
697 {
698 #ifdef RGTL_SQT_OBJECTS_DEBUG_QUERY
699 if (this->internal_.query_closest_debug_)
700 {
701 std::cout << " Checked " << this->checked_count_
702 << " of " << this->internal_.number_of_objects()
703 << " objects." << std::endl;
704 }
705 #endif
706 // Copy the final object id list to the output.
707 std::vector<closest_object_entry>& best = this->best_;
708 for (int i=0; i < k; ++i)
709 {
710 if (best[i].distance_squared >= 0)
711 {
712 #ifdef RGTL_SQT_OBJECTS_DEBUG_QUERY
713 if (this->internal_.query_closest_debug_)
714 {
715 std::cout << i
716 << ": id " << best[i].id
717 << ", d " << std::sqrt(best[i].distance_squared) << std::endl;
718 }
719 #endif
720 if (ids)
721 {
722 ids[i] = best[i].id;
723 }
724 if (squared_distances)
725 {
726 squared_distances[i] = best[i].distance_squared;
727 }
728 if (points)
729 {
730 for (unsigned int a=0; a < D; ++a)
731 {
732 points[i*D+a] = best[i].point[a];
733 }
734 }
735 }
736 else
737 {
738 return i;
739 }
740 }
741 return k;
742 }
743
744 //----------------------------------------------------------------------------
745 template <unsigned int D>
746 void
747 rgtl_sqt_objects_query_closest<D>
set_bound(double bound)748 ::set_bound(double bound)
749 {
750 this->bound_ = bound;
751 this->radius_ = std::sqrt(bound);
752 }
753
754 //----------------------------------------------------------------------------
755 template <unsigned int D>
756 void
757 rgtl_sqt_objects_query_closest<D>
update_bound(double bound)758 ::update_bound(double bound)
759 {
760 if (bound >= 0 && bound < this->bound_)
761 {
762 this->set_bound(bound);
763 #ifdef RGTL_SQT_OBJECTS_DEBUG_QUERY
764 if (this->internal_.query_closest_debug_)
765 {
766 std::cout << " Reduced bound to " << this->bound_ << std::endl;
767 }
768 #endif
769 }
770 }
771
772 //----------------------------------------------------------------------------
773 template <unsigned int D, unsigned int Face>
774 class rgtl_sqt_objects_query_closest_face
775 {
776 public:
777 typedef rgtl_sqt_objects_face<D, Face> face_type;
778 typedef rgtl_sqt_objects_internal<D> internal_type;
779 typedef rgtl_sqt_objects_query_closest<D> qc_type;
780 typedef typename face_type::cell_bounds_type cell_bounds_type;
781 typedef typename face_type::cell_location_type cell_location_type;
782 typedef typename face_type::cell_index_type cell_index_type;
783 typedef typename face_type::child_index_type child_index_type;
784 typedef typename face_type::leaf_data_type leaf_data_type;
785 typedef typename face_type::node_data_type node_data_type;
786 typedef rgtl_sqt_objects_cell_data<D> cell_data_type;
787 typedef typename leaf_data_type::cone_bounds_type cone_bounds_type;
788
rgtl_sqt_objects_query_closest_face(face_type const & face,qc_type & qc)789 rgtl_sqt_objects_query_closest_face(face_type const& face, qc_type& qc):
790 internal_(qc.internal_), face_(face), qc_(qc) {}
791
query(double const p[D],int k,double const u[D-1])792 void query(double const p[D], int k, double const u[D-1])
793 {
794 // Recursively visit the tree starting at the root.
795 this->query_impl(cell_location_type(Face), cell_index_type(), p, k, u);
796 }
797
798 void query_impl(cell_location_type const& cell,
799 cell_index_type cell_index,
800 double const p[D], int k, double const u[D-1]);
801
802 double compute_disc_nearest(double query_distance,
803 double query_angle, double query_depth,
804 double cone_angle, double clip_depth) const;
805 bool disjoint(cell_data_type const* cell_data,
806 double& nearest_squared) const;
807
dot(cone_bounds_type const u[D],double const v[D])808 static double dot(cone_bounds_type const u[D], double const v[D])
809 {
810 double d = 0;
811 for (unsigned int a=0; a < D; ++a)
812 {
813 d += u[a]*v[a];
814 }
815 return d;
816 }
817
818 private:
819 internal_type const& internal_;
820 face_type const& face_;
821 qc_type& qc_;
822 };
823
824 //----------------------------------------------------------------------------
825 template <unsigned int D, unsigned int Face>
826 void
827 rgtl_sqt_objects_query_closest_face<D, Face>
query_impl(cell_location_type const & cell,cell_index_type cell_index,double const p[D],int k,double const u[D-1])828 ::query_impl(cell_location_type const& cell, cell_index_type cell_index,
829 double const p[D], int k, double const u[D-1])
830 {
831 #ifdef RGTL_SQT_OBJECTS_DEBUG_QUERY
832 if (this->internal_.query_closest_debug_)
833 {
834 std::cout << "Considering cell " << cell << std::endl;
835 }
836 #endif
837
838 if (this->face_.tree().has_children(cell_index))
839 {
840 // Perform a fast-reject test if the current bounding sphere does
841 // not intersect the cell bounding cone.
842 double nearest_squared;
843 if (node_data_type const* nd =
844 this->face_.tree().get_node_data(cell_index))
845 {
846 if (this->disjoint(nd, nearest_squared))
847 {
848 #ifdef RGTL_SQT_OBJECTS_DEBUG_QUERY
849 if (this->internal_.query_closest_debug_)
850 {
851 std::cout << " node is disjoint" << std::endl;
852 }
853 #endif
854 return;
855 }
856 }
857 else
858 {
859 std::abort();
860 }
861
862 // This is a node. Compute the child containing the ray, if any.
863 // Use it to order child visitation to visit cells closer to the
864 // query point first.
865 unsigned int child_xor = 0;
866 if (u)
867 {
868 cell_bounds_type upper(cell.get_child(child_index_type((1<<(D-1))-1)));
869 for (unsigned int j=0; j < D-1; ++j)
870 {
871 if (u[j] >= upper.origin(j))
872 {
873 child_xor |= (1<<j);
874 }
875 }
876 }
877
878 // Recursively query each child.
879 for (unsigned int i = 0;
880 i < (1<<(D-1)) && this->qc_.bound_ >= nearest_squared; ++i)
881 {
882 child_index_type child_index(i^child_xor);
883 this->query_impl(cell.get_child(child_index),
884 this->face_.tree().get_child(cell_index,
885 child_index),
886 p, k, u);
887 }
888 }
889 else if (leaf_data_type const* ld =
890 this->face_.tree().get_leaf_data(cell_index))
891 {
892 // Perform a fast-reject test if the current bounding sphere does
893 // not intersect the cell bounding cone.
894 double nearest_squared;
895 if (this->disjoint(ld, nearest_squared))
896 {
897 #ifdef RGTL_SQT_OBJECTS_DEBUG_QUERY
898 if (this->internal_.query_closest_debug_)
899 {
900 std::cout << " leaf is disjoint" << std::endl;
901 }
902 #endif
903 return;
904 }
905
906 #ifdef RGTL_SQT_OBJECTS_DEBUG_QUERY
907 if (this->internal_.query_closest_debug_)
908 {
909 if (ld->index_begin < ld->index_end)
910 {
911 std::cout << " checking objects" << std::endl;
912 }
913 else
914 {
915 std::cout << " no objects" << std::endl;
916 }
917 }
918 #endif
919
920 // Test the objects in this leaf.
921 typedef typename leaf_data_type::index_type index_type;
922 for (index_type i=ld->index_begin;
923 i != ld->index_end && this->qc_.bound_ >= nearest_squared; ++i)
924 {
925 int id = this->face_.object_ids_[i];
926 if (this->internal_.visit_once(id))
927 {
928 this->qc_.check_object(p, k, id);
929 }
930 }
931 }
932 }
933
934 //----------------------------------------------------------------------------
935 template <unsigned int D, unsigned int Face>
936 double
937 rgtl_sqt_objects_query_closest_face<D, Face>
compute_disc_nearest(double query_distance,double query_angle,double query_depth,double cone_angle,double clip_depth) const938 ::compute_disc_nearest(double query_distance,
939 double query_angle, double query_depth,
940 double cone_angle, double clip_depth) const
941 {
942 // The disc can be formed by intersecting a cylinder and the clip
943 // plane. If the query point is outside the cylinder it is closest
944 // to the disc boundary. Otherwise it is closest to the disc
945 // interior.
946 double query_r = std::sin(query_angle)*query_distance;
947 double cylinder_r = std::tan(cone_angle)*clip_depth;
948 double distance_to_plane = query_depth - clip_depth;
949 double distance_squared = distance_to_plane*distance_to_plane;
950 if (query_r > cylinder_r)
951 {
952 // Query point is closest to the disc boundary.
953 double distance_to_cylinder = query_r - cylinder_r;
954 distance_squared += distance_to_cylinder*distance_to_cylinder;
955 }
956 else
957 {
958 // Query point is closest to the disc interior.
959 }
960 return distance_squared;
961 }
962
963 //----------------------------------------------------------------------------
964 template <unsigned int D, unsigned int Face>
965 bool
966 rgtl_sqt_objects_query_closest_face<D, Face>
disjoint(cell_data_type const * cell_data,double & nearest_squared) const967 ::disjoint(cell_data_type const* cell_data, double& nearest_squared) const
968 {
969 // Test the current bounding sphere against the cell depth range.
970 cone_bounds_type const* a = cell_data->cone_axis;
971 double const* c = this->qc_.center_direction_;
972 double a_dot_c = dot(a, c);
973 if (a_dot_c+this->qc_.radius_ < cell_data->depth_min)
974 {
975 // The bounding sphere is completely in front of the cell.
976 return true;
977 }
978 if (a_dot_c-this->qc_.radius_ > cell_data->depth_max)
979 {
980 // The bounding sphere is completely behind the cell.
981 return true;
982 }
983
984 // Test the current bounding sphere against the cell bounding cone.
985 double const beta = cell_data->cone_angle;
986 double const theta = std::acos(a_dot_c / this->qc_.center_depth_);
987 if (theta <= beta)
988 {
989 // The sphere center is inside the cone.
990 if (a_dot_c < cell_data->depth_min)
991 {
992 // Query point is closest to near disc interior.
993 double distance_to_near_plane = cell_data->depth_min - a_dot_c;
994 nearest_squared = distance_to_near_plane*distance_to_near_plane;
995 }
996 else if (a_dot_c > cell_data->depth_max)
997 {
998 // Query point is closest to the far disc.
999 nearest_squared = this->compute_disc_nearest(this->qc_.center_depth_,
1000 theta, a_dot_c, beta,
1001 cell_data->depth_max);
1002 }
1003 else
1004 {
1005 // Query point is inside the clipped cone.
1006 nearest_squared = 0;
1007 }
1008
1009 // If the distance to the nearest is at least as far as the
1010 // current bound then the sphere is disjoint.
1011 return nearest_squared >= this->qc_.bound_;
1012 }
1013
1014 double const phi = beta + vnl_math::pi / 2;
1015 if (theta >= phi)
1016 {
1017 // The sphere center is closest to the cone tip.
1018 if (this->qc_.center_depth_squared_ > this->qc_.bound_)
1019 {
1020 // The sphere is outside the cone.
1021 return true;
1022 }
1023 else
1024 {
1025 // Query point is closest to the near disc.
1026 nearest_squared = this->compute_disc_nearest(this->qc_.center_depth_,
1027 theta, a_dot_c, beta,
1028 cell_data->depth_min);
1029
1030 // If the distance to the nearest is at least as far as the
1031 // current bound then the sphere is disjoint.
1032 return nearest_squared >= this->qc_.bound_;
1033 }
1034 }
1035
1036 // The sphere center is closest to the cone surface.
1037 double c_dot_c = this->qc_.center_depth_squared_;
1038 double distance_to_cone_surface =
1039 (std::cos(phi)*a_dot_c + std::sin(phi)*std::sqrt(c_dot_c - a_dot_c*a_dot_c));
1040 if (this->qc_.radius_ < distance_to_cone_surface)
1041 {
1042 // The sphere is outside the cone.
1043 return true;
1044 }
1045 else
1046 {
1047 // The sphere center is outside the cone.
1048 // Test against the far normal cone.
1049 double const alpha = vnl_math::pi/2 - beta;
1050 double cos_beta = std::cos(beta);
1051 double cos_beta_2 = cos_beta * cos_beta;
1052 double scale_far = cell_data->depth_max / cos_beta_2;
1053 double cos_gamma_far =
1054 ((scale_far - a_dot_c) /
1055 std::sqrt(c_dot_c - 2*scale_far*a_dot_c + scale_far*scale_far));
1056 double gamma_far = std::acos(cos_gamma_far);
1057 if (gamma_far > alpha)
1058 {
1059 // Query point is behind the far normal cone and outside the
1060 // primal cone. It is closest to the far disc boundary.
1061 double query_r = std::sin(theta)*this->qc_.center_depth_;
1062 double cylinder_r = std::tan(beta)*cell_data->depth_max;
1063 double distance_to_far_plane = a_dot_c - cell_data->depth_max;
1064 double distance_to_far_cylinder = query_r - cylinder_r;
1065 nearest_squared =
1066 (distance_to_far_plane*distance_to_far_plane +
1067 distance_to_far_cylinder*distance_to_far_cylinder);
1068 }
1069 else
1070 {
1071 // Test against the near normal cone.
1072 double scale_near = cell_data->depth_min / cos_beta_2;
1073 double cos_gamma_near =
1074 ((scale_near - a_dot_c) /
1075 std::sqrt(c_dot_c - 2*scale_near*a_dot_c + scale_near*scale_near));
1076 double gamma_near = std::acos(cos_gamma_near);
1077 if (gamma_near < alpha)
1078 {
1079 // Query point is in front of the near normal cone and outside
1080 // the primal cone. It is closest to the near disc.
1081 nearest_squared = this->compute_disc_nearest(this->qc_.center_depth_,
1082 theta, a_dot_c, beta,
1083 cell_data->depth_min);
1084 }
1085 else
1086 {
1087 // Query point is closest to the cone surface.
1088 nearest_squared = distance_to_cone_surface*distance_to_cone_surface;
1089 }
1090 }
1091
1092 // If the distance to the nearest is at least as far as the
1093 // current bound then the sphere is disjoint.
1094 return nearest_squared >= this->qc_.bound_;
1095 }
1096 }
1097
1098 //----------------------------------------------------------------------------
1099 template <unsigned int D>
1100 int
1101 rgtl_sqt_objects_internal<D>
query_closest(double const p[D],int k,int * ids,double * squared_distances,double * points,double bound_squared) const1102 ::query_closest(double const p[D], int k, int* ids,
1103 double* squared_distances, double* points,
1104 double bound_squared) const
1105 {
1106 // Setup initial query sphere radius.
1107 if (bound_squared < 0)
1108 {
1109 bound_squared = std::numeric_limits<double>::infinity();
1110 }
1111 #ifdef RGTL_SQT_OBJECTS_DEBUG_QUERY
1112 else if (this->query_closest_debug_)
1113 {
1114 std::cout << "User initial bound " << bound_squared << std::endl;
1115 }
1116 #endif
1117
1118 // Keep track objects already tested to avoid duplicating tests.
1119 this->object_once_.reset();
1120
1121 // Collect the results for each face. Start with the face
1122 // containing the query point.
1123 rgtl_sqt_objects_query_closest<D> qc(*this, p, k, bound_squared);
1124 unsigned int f = qc.center_face_;
1125 this->face(f).query_closest(p, k, qc.center_parameters_, qc);
1126 for (unsigned int i=0; i < (D<<1); ++i)
1127 {
1128 if (i != f)
1129 {
1130 this->face(i).query_closest(p, k, 0, qc);
1131 }
1132 }
1133 return qc.get_result(k, ids, squared_distances, points);
1134 }
1135
1136 //----------------------------------------------------------------------------
1137 template <unsigned int D, unsigned int Face>
1138 void
build(sqt_object_set_ptr & oa)1139 rgtl_sqt_objects_face<D, Face>::build(sqt_object_set_ptr& oa)
1140 {
1141 // Down-cast the pointer to get the per-face object set.
1142 sqt_object_set_face_ptr
1143 oaf(static_cast<rgtl_sqt_object_set_face<D, Face>*>(oa.release()));
1144
1145 // Construct the tree starting at the root cell.
1146 this->build(cell_geometry_type(cell_location_type(Face)),
1147 cell_index_type(), oaf);
1148 }
1149
1150 //----------------------------------------------------------------------------
1151 template <unsigned int D, unsigned int Face>
1152 void
1153 rgtl_sqt_objects_face<D, Face>
build(cell_geometry_type const & cell_geometry,cell_index_type cell_index,sqt_object_set_face_ptr & oa)1154 ::build(cell_geometry_type const& cell_geometry, cell_index_type cell_index,
1155 sqt_object_set_face_ptr& oa)
1156 {
1157 cell_location_type const& cell = cell_geometry.location();
1158 #ifdef RGTL_SQT_OBJECTS_DEBUG_BUILD2
1159 exception_stack es(cell); (void)es;
1160 #endif
1161 #ifdef RGTL_SQT_OBJECTS_DEBUG_BUILD
1162 std::cout << "Considering " << oa->number_of_objects()
1163 << " objects in cell " << cell << std::endl;
1164 #endif
1165 bool tooDeep = cell.level() >= this->internal_.max_level();
1166 bool tooMany = oa->number_of_objects() > this->internal_.max_per_leaf();
1167 if (tooMany && !tooDeep)
1168 {
1169 // Divide this cell.
1170 this->tree_.subdivide(cell_index);
1171
1172 // Compute the bounding cone for this node.
1173 node_data_type node_data;
1174 cell_geometry.get_cone(node_data.cone_axis, node_data.cone_angle);
1175
1176 // Compute the bounding depth range for this node.
1177 oa->get_depth_range(node_data.cone_axis,
1178 node_data.depth_min, node_data.depth_max);
1179
1180 // Store data in the node.
1181 this->tree_.set_node_data(cell_index, &node_data);
1182
1183 // Distribute objects into children.
1184 sqt_object_set_face_ptr children[1<<(D-1)];
1185 oa->split(cell_geometry, children);
1186
1187 // Erase memory used by the object array for this cell.
1188 oa.reset(0);
1189
1190 // Compute the child cell geometries.
1191 typename cell_geometry_type::children_type child_geometry(cell_geometry);
1192
1193 // Build the children recursively.
1194 for (child_index_type i(0); i < (1<<(D-1)); ++i)
1195 {
1196 this->build(child_geometry[i],
1197 this->tree_.get_child(cell_index, i),
1198 children[i]);
1199 }
1200 }
1201 else if (oa->number_of_objects() > 0)
1202 {
1203 // We will not divide this cell further.
1204 // Store the objects for this cell.
1205 #ifdef RGTL_SQT_OBJECTS_DEBUG_BUILD
1206 std::cout << "Storing " << oa->number_of_objects() << " objects in cell "
1207 << cell << std::endl;
1208 #endif
1209 typedef typename leaf_data_type::index_type index_type;
1210 index_type index_begin = index_type(this->object_ids_.size());
1211 for (int i=0; i < oa->number_of_objects(); ++i)
1212 {
1213 this->object_ids_.push_back(oa->original_id(i));
1214 }
1215 index_type index_end = index_type(this->object_ids_.size());
1216 leaf_data_type leaf_data(index_begin, index_end);
1217
1218 // Compute the bounding cone for this leaf.
1219 cell_geometry.get_cone(leaf_data.cone_axis, leaf_data.cone_angle);
1220
1221 // Compute the bounding depth range for this leaf.
1222 oa->get_depth_range(leaf_data.cone_axis,
1223 leaf_data.depth_min, leaf_data.depth_max);
1224
1225 // Store the data in the leaf.
1226 this->tree_.set_leaf_data(cell_index, &leaf_data);
1227 }
1228 }
1229
1230 //----------------------------------------------------------------------------
1231 template <unsigned int D, unsigned int Face>
1232 bool
query_ray(double const d[D],double x[D],double * s) const1233 rgtl_sqt_objects_face<D, Face>::query_ray(double const d[D],
1234 double x[D], double* s) const
1235 {
1236 double u[D-1];
1237 space::direction_to_parameters(d, u);
1238 return this->query_ray(cell_location_type(Face), cell_index_type(),
1239 u, d, x, s);
1240 }
1241
1242 //----------------------------------------------------------------------------
1243 template <unsigned int D, unsigned int Face>
1244 bool
query_ray(cell_location_type const & cell,cell_index_type cell_index,double const u[D-1],double const d[D],double x[D],double * s) const1245 rgtl_sqt_objects_face<D, Face>::query_ray(cell_location_type const& cell,
1246 cell_index_type cell_index,
1247 double const u[D-1],
1248 double const d[D],
1249 double x[D],
1250 double* s) const
1251 {
1252 if (this->tree_.has_children(cell_index))
1253 {
1254 // This is a node. Compute the child containing the ray.
1255 child_index_type child_index(0);
1256 cell_bounds_type upper(cell.get_child(child_index_type((1<<(D-1))-1)));
1257 for (unsigned int j=0; j < D-1; ++j)
1258 {
1259 if (u[j] >= upper.origin(j))
1260 {
1261 child_index |= (1<<j);
1262 }
1263 }
1264
1265 // Recurse into the chosen child.
1266 return this->query_ray(cell.get_child(child_index),
1267 this->tree_.get_child(cell_index, child_index),
1268 u, d, x, s);
1269 }
1270 else if (leaf_data_type const* ld = this->tree_.get_leaf_data(cell_index))
1271 {
1272 // Test the objects in this leaf.
1273 bool found = false;
1274 double min_s = std::numeric_limits<double>::infinity();
1275 typedef typename leaf_data_type::index_type index_type;
1276 for (index_type i=ld->index_begin; i != ld->index_end; ++i)
1277 {
1278 int id = this->object_ids_[i];
1279 double cur_x[D];
1280 double cur_s;
1281 if (this->query_ray(id, d, cur_x, &cur_s))
1282 {
1283 found = true;
1284 if (cur_s < min_s)
1285 {
1286 min_s = cur_s;
1287 if (x)
1288 {
1289 for (unsigned int a=0; a < D; ++a)
1290 {
1291 x[a] = cur_x[a];
1292 }
1293 }
1294 if (s)
1295 {
1296 *s = min_s;
1297 }
1298 }
1299 }
1300 }
1301 return found;
1302 }
1303 return false;
1304 }
1305
1306 //----------------------------------------------------------------------------
1307 template <unsigned int D, unsigned int Face>
1308 bool
query_ray(int id,double const d[D],double x[D],double * s) const1309 rgtl_sqt_objects_face<D, Face>::query_ray(int id,
1310 double const d[D],
1311 double x[D],
1312 double* s) const
1313 {
1314 return
1315 this->object_array().object_intersects_ray(id,
1316 this->origin().data_block(),
1317 d, x, s);
1318 }
1319
1320 //----------------------------------------------------------------------------
1321 template <unsigned int D, unsigned int Face>
1322 void
1323 rgtl_sqt_objects_face<D, Face>
query_closest(double const p[D],int k,double const u[D-1],rgtl_sqt_objects_query_closest<D> & qc) const1324 ::query_closest(double const p[D], int k, double const u[D-1],
1325 rgtl_sqt_objects_query_closest<D>& qc) const
1326 {
1327 rgtl_sqt_objects_query_closest_face<D, Face> qcf(*this, qc);
1328 qcf.query(p, k, u);
1329 }
1330
1331 //----------------------------------------------------------------------------
1332 template <unsigned int D>
rgtl_sqt_objects(object_array_type const & oa)1333 rgtl_sqt_objects<D>::rgtl_sqt_objects(object_array_type const& oa):
1334 internal_(new rgtl_sqt_objects_internal<D>(oa))
1335 {
1336 }
1337
1338 //----------------------------------------------------------------------------
1339 template <unsigned int D>
rgtl_sqt_objects(sqt_object_array_type const & soa,double const origin[D],int ml,int mpl)1340 rgtl_sqt_objects<D>::rgtl_sqt_objects(sqt_object_array_type const& soa,
1341 double const origin[D],
1342 int ml, int mpl):
1343 internal_(new rgtl_sqt_objects_internal<D>(soa.original()))
1344 {
1345 this->build(soa, origin, ml, mpl);
1346 }
1347
1348 //----------------------------------------------------------------------------
1349 template <unsigned int D>
~rgtl_sqt_objects()1350 rgtl_sqt_objects<D>::~rgtl_sqt_objects()
1351 {
1352 }
1353
1354 //----------------------------------------------------------------------------
1355 template <unsigned int D>
build(sqt_object_array_type const & soa,double const origin[D],int ml,int mpl)1356 void rgtl_sqt_objects<D>::build(sqt_object_array_type const& soa,
1357 double const origin[D],
1358 int ml, int mpl)
1359 {
1360 this->internal_->build(soa, origin, ml, mpl);
1361 }
1362
1363 //----------------------------------------------------------------------------
1364 template <unsigned int D>
1365 bool
query_ray(double const d[D],double x[D],double * s) const1366 rgtl_sqt_objects<D>::query_ray(double const d[D],
1367 double x[D], double* s) const
1368 {
1369 return this->internal_->query_ray(d, x, s);
1370 }
1371
1372 //----------------------------------------------------------------------------
1373 template <unsigned int D>
1374 int
query_closest(double const p[D],int k,int * ids,double * squared_distances,double * points,double bound_squared) const1375 rgtl_sqt_objects<D>::query_closest(double const p[D], int k, int* ids,
1376 double* squared_distances, double* points,
1377 double bound_squared) const
1378 {
1379 return this->internal_->query_closest(p, k, ids, squared_distances, points,
1380 bound_squared);
1381 }
1382
1383 //----------------------------------------------------------------------------
1384 template <unsigned int D>
origin(unsigned int a) const1385 double rgtl_sqt_objects<D>::origin(unsigned int a) const
1386 {
1387 assert(a < D);
1388 return this->internal_->origin(a);
1389 }
1390
1391 //----------------------------------------------------------------------------
1392 template <unsigned int D>
origin() const1393 vnl_vector_fixed<double,D> const& rgtl_sqt_objects<D>::origin() const
1394 {
1395 return this->internal_->origin();
1396 }
1397
1398 //----------------------------------------------------------------------------
1399 template <unsigned int D>
compute_bounds(double bounds[D][2]) const1400 void rgtl_sqt_objects<D>::compute_bounds(double bounds[D][2]) const
1401 {
1402 // Start with the bounds of the objects.
1403 this->internal_->object_array().compute_bounds(bounds);
1404
1405 // Update the bounds to contain the origin.
1406 vnl_vector_fixed<double,D> const& p = this->origin();
1407 for (unsigned int a=0; a < D; ++a)
1408 {
1409 if (p[a] < bounds[a][0])
1410 {
1411 bounds[a][0] = p[a];
1412 }
1413 if (p[a] > bounds[a][1])
1414 {
1415 bounds[a][1] = p[a];
1416 }
1417 }
1418 }
1419
1420 //----------------------------------------------------------------------------
1421 template <unsigned int D>
1422 bool
1423 rgtl_sqt_objects<D>
has_children(unsigned int face,cell_index_type cell_index) const1424 ::has_children(unsigned int face, cell_index_type cell_index) const
1425 {
1426 assert(face < (D<<1));
1427 return this->internal_->face(face).tree().has_children(cell_index);
1428 }
1429
1430 //----------------------------------------------------------------------------
1431 template <unsigned int D>
1432 typename rgtl_sqt_objects<D>::cell_index_type
1433 rgtl_sqt_objects<D>
get_child(unsigned int face,cell_index_type cell_index,child_index_type child) const1434 ::get_child(unsigned int face, cell_index_type cell_index,
1435 child_index_type child) const
1436 {
1437 assert(face < (D<<1));
1438 return this->internal_->face(face).tree().get_child(cell_index, child);
1439 }
1440
1441 //----------------------------------------------------------------------------
1442 template <unsigned int D>
1443 bool
1444 rgtl_sqt_objects<D>
get_depth_range(unsigned int face,cell_index_type cell_index,double & depth_min,double & depth_max) const1445 ::get_depth_range(unsigned int face, cell_index_type cell_index,
1446 double& depth_min, double& depth_max) const
1447 {
1448 assert(face < (D<<1));
1449 typedef rgtl_sqt_objects_face_base<D> face_base;
1450 typedef typename face_base::tree_type tree_type;
1451 typedef typename face_base::node_data_type node_data_type;
1452 typedef typename face_base::leaf_data_type leaf_data_type;
1453 tree_type const& tree = this->internal_->face(face).tree();
1454 if (tree.has_children(cell_index))
1455 {
1456 if (node_data_type const* nd = tree.get_node_data(cell_index))
1457 {
1458 depth_min = nd->depth_min;
1459 depth_max = nd->depth_max;
1460 return true;
1461 }
1462 }
1463 else
1464 {
1465 if (leaf_data_type const* ld = tree.get_leaf_data(cell_index))
1466 {
1467 depth_min = ld->depth_min;
1468 depth_max = ld->depth_max;
1469 return true;
1470 }
1471 }
1472 return false;
1473 }
1474
1475 //----------------------------------------------------------------------------
1476 template <unsigned int D>
1477 void
1478 rgtl_sqt_objects<D>
set_query_closest_debug(bool b)1479 ::set_query_closest_debug(bool b)
1480 {
1481 this->internal_->set_query_closest_debug(b);
1482 }
1483
1484 //----------------------------------------------------------------------------
1485 template <unsigned int D>
1486 template <class Serializer>
serialize(Serializer & sr)1487 void rgtl_sqt_objects<D>::serialize(Serializer& sr)
1488 {
1489 sr & *(this->internal_);
1490 }
1491
1492 //----------------------------------------------------------------------------
1493 #define RGTL_SQT_OBJECTS_INSTANTIATE(D) \
1494 template class rgtl_sqt_objects_internal< D >; \
1495 template class rgtl_sqt_objects< D >; \
1496 template void rgtl_sqt_objects< D > \
1497 ::serialize<rgtl_serialize_ostream>(rgtl_serialize_ostream&); \
1498 template void rgtl_sqt_objects< D > \
1499 ::serialize<rgtl_serialize_istream>(rgtl_serialize_istream&)
1500 #define RGTL_SQT_OBJECTS_FACE_INSTANTIATE(D, Face) \
1501 template class rgtl_sqt_objects_face< D , Face >
1502
1503 #endif
1504