intersectionPrimitive.h
Go to the documentation of this file.
1 // Copyright 2014 Nicolas Mellado
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //
15 // -------------------------------------------------------------------------- //
16 //
17 // Authors: Nicolas Mellado
18 //
19 // An implementation of the Super 4-points Congruent Sets (Super 4PCS)
20 // algorithm presented in:
21 //
22 // Super 4PCS: Fast Global Pointcloud Registration via Smart Indexing
23 // Nicolas Mellado, Dror Aiger, Niloy J. Mitra
24 // Symposium on Geometry Processing 2014.
25 //
26 // Data acquisition in large-scale scenes regularly involves accumulating
27 // information across multiple scans. A common approach is to locally align scan
28 // pairs using Iterative Closest Point (ICP) algorithm (or its variants), but
29 // requires static scenes and small motion between scan pairs. This prevents
30 // accumulating data across multiple scan sessions and/or different acquisition
31 // modalities (e.g., stereo, depth scans). Alternatively, one can use a global
32 // registration algorithm allowing scans to be in arbitrary initial poses. The
33 // state-of-the-art global registration algorithm, 4PCS, however has a quadratic
34 // time complexity in the number of data points. This vastly limits its
35 // applicability to acquisition of large environments. We present Super 4PCS for
36 // global pointcloud registration that is optimal, i.e., runs in linear time (in
37 // the number of data points) and is also output sensitive in the complexity of
38 // the alignment problem based on the (unknown) overlap across scan pairs.
39 // Technically, we map the algorithm as an ‘instance problem’ and solve it
40 // efficiently using a smart indexing data organization. The algorithm is
41 // simple, memory-efficient, and fast. We demonstrate that Super 4PCS results in
42 // significant speedup over alternative approaches and allows unstructured
43 // efficient acquisition of scenes at scales previously not possible. Complete
44 // source code and datasets are available for research use at
45 // http://geometry.cs.ucl.ac.uk/projects/2014/super4PCS/.
46 
47 
48 #ifndef _OPENGR_ACCELERATORS_INTERSECTION_PRIMITIVES_H_
49 #define _OPENGR_ACCELERATORS_INTERSECTION_PRIMITIVES_H_
50 
51 #ifndef SQR
52 #define SQR(a) ((a)*(a))
53 #endif
54 
55 #include <Eigen/Core>
56 
57 namespace gr{
58 
59 template <class Point, int _dim, typename Scalar>
61 private:
62  const Point _center;
63  Scalar _radius;
64 
65 
66  //! \brief UnaryExpr to apply floor with arbitrary quantification step e
67  struct CustomFloorExpr{
68  inline CustomFloorExpr(Scalar e) : m_e(e) {}
69  inline const Scalar operator()(const Scalar &x) const
70  {
71  return std::round(x/m_e) * m_e;
72  }
73 
74  Scalar m_e;
75  };
76 
77 public:
78  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
79  enum { Dim = _dim};
80 
81  inline HyperSphere(const Point& center, Scalar radius)
82  : _center(center), _radius(radius) { }
83 
84  inline HyperSphere(const HyperSphere<Point, _dim, Scalar>& other)
85  : _center(other._center), _radius(other._radius) { }
86 
87  //! \brief Construct a copy of the instance with a quantified radius and pos
88  inline HyperSphere<Point, _dim, Scalar> quantified ( Scalar eps ) const
89  {
90  CustomFloorExpr expr (eps);
91  return HyperSphere<Point, _dim, Scalar>(_center.unaryExpr(expr),
92  expr(_radius));
93  }
94 
95  //! \brief Comparison operator comparing first the radius then the position
96  inline bool operator<(const HyperSphere<Point, _dim, Scalar>& other) const{
97  if (_radius != other._radius)
98  return _radius < other._radius;
99  for( int i = 0; i < Dim; i++ ) {
100  if (_center[i] == other._center[i]) continue;
101  if (_center[i] < other._center[i]) return true;
102  return false;
103  }
104  return false;
105  }
106 
107  //! Implicit conversion operator to Eigen vectors
108  inline operator Point() const { return _center; }
109 
110  /*!
111  * \implements Arvo, James,
112  * A Simple Method for Box-Sphere Intersection Testing,
113  * Graphics Gems, p. 335-339, code: p. 730-732, BoxSphere.c.
114  */
115  inline bool intersect( const Point& nodeCenter, Scalar halfEdgeLength) const
116  {
117  const Point min = nodeCenter.array() - halfEdgeLength;
118  const Point max = nodeCenter.array() + halfEdgeLength;
119  const Point sqmin = (_center.array() - min.array()).square();
120  const Point sqmax = (_center.array() - max.array()).square();
121 
122  // The computation of dmin below is equivalent to:
123  //for( int i = 0; i < Dim; i++ ) {
124  //if( _center[i] < min[i] ) dmin += sqmin[i]; else
125  //if( _center[i] > max[i] ) dmin += sqmax[i];
126  //}
127 
128  Scalar dmin = (_center.array() < min.array())
129  .select(
130  sqmin,
131  (_center.array() > max.array()).select(sqmax,Point::Zero())
132  ).sum();
133 
134  return ( dmin < _radius*_radius &&
135  _radius*_radius < sqmin.cwiseMax(sqmax).sum() );
136  }
137 
138  /*!
139  * \brief intersectFast Fast but inacurate intersection test
140  * \param nodeCenter
141  * \param halfEdgeLength
142  * \return
143  *
144  * Check if the node center is inside the Hypersphere (radius grown by
145  * halfEdgeLength.
146  */
147  inline bool intersectFast( const Point& nodeCenter, Scalar halfEdgeLength) const
148  {
149  return SQR((nodeCenter-_center).norm()-halfEdgeLength) <= _radius;
150  }
151 
152  inline bool intersectPoint( const Point& pos, Scalar epsilon ) const
153  {
154  return SQR((pos - _center).norm()-_radius) < SQR(epsilon);
155  }
156 
157  static inline bool intersectPoint( const Point& pos, Scalar epsilon,
158  const Point& center, const Scalar &radius )
159  {
160  return SQR((pos - center).norm()-radius) < SQR(epsilon);
161  }
162 
163  inline const Point& center() const {return _center;}
164  inline const Scalar & radius() const {return _radius;}
165  inline Scalar& radius() { return _radius; }
166 };
167 
168 } // namespace gr
169 
170 #endif
bool intersectPoint(const Point &pos, Scalar epsilon) const
Definition: intersectionPrimitive.h:152
const Scalar & radius() const
Definition: intersectionPrimitive.h:164
#define SQR(a)
Definition: intersectionPrimitive.h:52
Definition: intersectionPrimitive.h:60
bool intersect(const Point &nodeCenter, Scalar halfEdgeLength) const
Definition: intersectionPrimitive.h:115
CongruentSetExplorationBase< Traits, PointType, TransformVisitor, PairFilteringFunctor, OptExts... >::Scalar ComputeTransformation(const InputRange1 &P, const InputRange2 &Q, Eigen::Ref< typename CongruentSetExplorationBase< Traits, PointType, TransformVisitor, PairFilteringFunctor, OptExts... >::MatrixType > transformation, const Sampler< PointType > &sampler, TransformVisitor &v)
Definition: congruentSetExplorationBase.hpp:61
HyperSphere(const HyperSphere< Point, _dim, Scalar > &other)
Definition: intersectionPrimitive.h:84
operator Point() const
Implicit conversion operator to Eigen vectors.
Definition: intersectionPrimitive.h:108
HyperSphere(const Point &center, Scalar radius)
Definition: intersectionPrimitive.h:81
bool operator<(const HyperSphere< Point, _dim, Scalar > &other) const
Comparison operator comparing first the radius then the position.
Definition: intersectionPrimitive.h:96
Scalar & radius()
Definition: intersectionPrimitive.h:165
HyperSphere< Point, _dim, Scalar > quantified(Scalar eps) const
Construct a copy of the instance with a quantified radius and pos.
Definition: intersectionPrimitive.h:88
const Point & center() const
Definition: intersectionPrimitive.h:163
static bool intersectPoint(const Point &pos, Scalar epsilon, const Point &center, const Scalar &radius)
Definition: intersectionPrimitive.h:157
bool intersectFast(const Point &nodeCenter, Scalar halfEdgeLength) const
intersectFast Fast but inacurate intersection test
Definition: intersectionPrimitive.h:147
Definition: intersectionPrimitive.h:79