snark
voxel_map.h
1 // This file is part of snark, a generic and flexible library
2 // for robotics research.
3 //
4 // Copyright (C) 2011 The University of Sydney
5 //
6 // snark is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 3 of the License, or (at your option) any later version.
10 //
11 // snark is distributed in the hope that it will be useful, but WITHOUT ANY
12 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
14 // for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with snark. If not, see <http://www.gnu.org/licenses/>.
18 
19 #ifndef SNARK_POINT_CLOUD_VOXELMAP_H
20 #define SNARK_POINT_CLOUD_VOXELMAP_H
21 
22 #include <boost/array.hpp>
23 #include <boost/functional/hash.hpp>
24 #include <boost/unordered_map.hpp>
25 #include <Eigen/Core>
26 #include <comma/base/types.h>
27 
28 namespace snark {
29 
32 template < typename Array, std::size_t Size >
33 struct array_hash : public std::unary_function< Array, std::size_t >
34 {
35  std::size_t operator()( Array const& array ) const
36  {
37  std::size_t seed = 0;
38  for( std::size_t i = 0; i < Size; ++i ) { boost::hash_combine( seed, array[i] ); }
39  return seed;
40  // return boost::hash_range( &array[0], &array[Size] ); // not so easy...
41  }
42 };
43 
49 template < typename V, unsigned int D, typename P = Eigen::Matrix< double, D, 1 > >
50 class voxel_map : public boost::unordered_map< boost::array< comma::int32, D >, V, snark::array_hash< boost::array< comma::int32, D >, D > >
51 {
52  public:
54  enum { dimensions = D };
55 
57  typedef V voxel_type;
58 
60  typedef P point_type;
61 
63  typedef boost::array< comma::int32, D > index_type;
64 
66  typedef boost::unordered_map< index_type, voxel_type, snark::array_hash< index_type, D > > base_type;
67 
69  typedef typename base_type::iterator iterator;
70 
72  typedef typename base_type::const_iterator const_iterator;
73 
76 
79 
81  iterator touch_at( const point_type& point );
82 
84  std::pair< iterator, bool > insert( const point_type& point, const voxel_type& voxel );
85 
87  index_type index_of( const point_type& point ) const;
88 
90  static index_type index_of( const point_type& point, const point_type& origin, const point_type& resolution );
91 
93  static index_type index_of( const point_type& point, const point_type& resolution );
94 
96  iterator find( const point_type& point );
97 
99  const_iterator find( const point_type& point ) const;
100 
102  iterator find( const index_type& index );
103 
105  const_iterator find( const index_type& index ) const;
106 
108  const point_type& origin() const;
109 
111  const point_type& resolution() const;
112 
113  private:
114  point_type origin_;
115  point_type resolution_;
116 };
117 
118 template < typename V, unsigned int D, typename P >
119 inline voxel_map< V, D, P >::voxel_map( const typename voxel_map< V, D, P >::point_type& origin, const typename voxel_map< V, D, P >::point_type& resolution )
120  : origin_( origin )
121  , resolution_( resolution )
122 {
123 }
124 
125 template < typename V, unsigned int D, typename P >
126 inline voxel_map< V, D, P >::voxel_map( const typename voxel_map< V, D, P >::point_type& resolution )
127  : origin_( point_type::Zero() ) // todo: use traits, if decoupling from eigen required
128  , resolution_( resolution )
129 {
130 }
131 
132 template < typename V, unsigned int D, typename P >
134 {
135  index_type index = index_of( point );
136  iterator it = this->base_type::find( index );
137  if( it != this->end() ) { return it; }
138  return this->base_type::insert( std::make_pair( index, voxel_type() ) ).first;
139 }
140 
141 template < typename V, unsigned int D, typename P >
142 inline std::pair< typename voxel_map< V, D, P >::iterator, bool > voxel_map< V, D, P >::insert( const typename voxel_map< V, D, P >::point_type& point, const typename voxel_map< V, D, P >::voxel_type& voxel )
143 {
144  return this->base_type::insert( std::make_pair( index_of( point ), voxel ) );
145 }
146 
147 namespace impl {
148 
149 static int negative_flooring_ = static_cast< int >( -1.5 ) == -1 ? -1 : static_cast< int >( -1.5 ) == -2 ? 0 : 0;
150 static int positive_flooring_ = static_cast< int >( 1.5 ) == 1 ? 0 : static_cast< int >( 1.5 ) == 2 ? -1 : -1;
151 
152 } // namespace impl {
153 
154 template < typename V, unsigned int D, typename P >
155 inline typename voxel_map< V, D, P >::index_type voxel_map< V, D, P >::index_of( const typename voxel_map< V, D, P >::point_type& point, const typename voxel_map< V, D, P >::point_type& origin, const typename voxel_map< V, D, P >::point_type& resolution )
156 {
157  point_type diff = ( point - origin ).array() / resolution.array();
158  index_type index;
159  for( unsigned int i = 0; i < dimensions; ++i )
160  {
161  int d = diff[i];
162  index[i] = d;
163  if( diff[i] == d ) { continue; }
164  index[i] += diff[i] < 0 ? impl::negative_flooring_ : ( d == 0 ? 0 : impl::positive_flooring_ );
165  }
166  return index;
167 }
168 
169 template < typename V, unsigned int D, typename P >
170 inline typename voxel_map< V, D, P >::index_type voxel_map< V, D, P >::index_of( const typename voxel_map< V, D, P >::point_type& point, const typename voxel_map< V, D, P >::point_type& resolution )
171 {
172  return index_of( point, point_type::Zero(), resolution );
173 }
174 
175 template < typename V, unsigned int D, typename P >
176 inline typename voxel_map< V, D, P >::index_type voxel_map< V, D, P >::index_of( const typename voxel_map< V, D, P >::point_type& point ) const
177 {
178  return index_of( point, origin_, resolution_ );
179 }
180 
181 template < typename V, unsigned int D, typename P >
182 inline typename voxel_map< V, D, P >::iterator voxel_map< V, D, P >::find( const typename voxel_map< V, D, P >::point_type& point )
183 {
184  index_type i = index_of( point );
185  return this->base_type::find( i );
186 }
187 
188 template < typename V, unsigned int D, typename P >
189 inline typename voxel_map< V, D, P >::const_iterator voxel_map< V, D, P >::find( const typename voxel_map< V, D, P >::point_type& point ) const
190 {
191  index_type i = index_of( point );
192  return this->base_type::find( i );
193 }
194 
195 template < typename V, unsigned int D, typename P >
196 inline typename voxel_map< V, D, P >::iterator voxel_map< V, D, P >::find( const typename voxel_map< V, D, P >::index_type& index )
197 {
198  return this->base_type::find( index ); // otherwise strange things happen... debug, when we have time
199 }
200 
201 template < typename V, unsigned int D, typename P >
202 inline typename voxel_map< V, D, P >::const_iterator voxel_map< V, D, P >::find( const typename voxel_map< V, D, P >::index_type& index ) const
203 {
204  return this->base_type::find( index ); // otherwise strange things happen... debug, when we have time
205 }
206 
207 template < typename V, unsigned int D, typename P >
208 inline const typename voxel_map< V, D, P >::point_type& voxel_map< V, D, P >::origin() const { return origin_; }
209 
210 template < typename V, unsigned int D, typename P >
211 inline const typename voxel_map< V, D, P >::point_type& voxel_map< V, D, P >::resolution() const { return resolution_; }
212 
213 } // namespace snark {
214 
215 #endif // SNARK_POINT_CLOUD_VOXELMAP_H