RINGMesh  Version 5.0.0
A programming library for geological model meshes
nn_search.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2012-2017, Association Scientifique pour la Geologie et ses
3  * Applications (ASGA). All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  * * Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * * Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * * Neither the name of ASGA nor the
13  * names of its contributors may be used to endorse or promote products
14  * derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
18  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ASGA BE LIABLE FOR ANY DIRECT,
20  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  *
27  * http://www.ring-team.org
28  *
29  * RING Project
30  * Ecole Nationale Superieure de Geologie - GeoRessources
31  * 2 Rue du Doyen Marcel Roubault - TSA 70605
32  * 54518 VANDOEUVRE-LES-NANCY
33  * FRANCE
34  */
35 
44 
46 
47 #include <geogram/points/kd_tree.h>
48 
49 namespace RINGMesh
50 {
51  template < index_t DIMENSION >
52  class NNSearch< DIMENSION >::Impl
53  {
54  public:
55  Impl( const std::vector< vecn< DIMENSION > >& vertices, bool copy )
56  : nn_tree_( GEO::NearestNeighborSearch::create( DIMENSION, "BNN" ) )
57  {
58  auto nb_vertices = static_cast< index_t >( vertices.size() );
59  if( copy )
60  {
61  nn_points_ = new double[nb_vertices * DIMENSION];
62  delete_points_ = true;
63  GEO::Memory::copy( nn_points_, vertices.data()->data(),
64  DIMENSION * nb_vertices * sizeof( double ) );
65  }
66  else
67  {
68  nn_points_ = const_cast< double* >( vertices.data()->data() );
69  delete_points_ = false;
70  }
71  nn_tree_->set_points( nb_vertices, nn_points_ );
72  }
73 
75  {
76  if( delete_points_ )
77  {
78  delete[] nn_points_;
79  }
80  }
81 
83  index_t index_in_nn_search, const vecn< DIMENSION >& center )
84  {
85  for( auto i : range( DIMENSION ) )
86  {
87  nn_points_[index_in_nn_search + i] = center[i];
88  }
89  }
90 
91  vecn< DIMENSION > point( index_t v ) const
92  {
93  vecn< DIMENSION > result;
94  for( auto i : range( DIMENSION ) )
95  {
96  result[i] = nn_points_[DIMENSION * v + i];
97  }
98  return result;
99  }
100 
101  index_t nb_points() const
102  {
103  return nn_tree_->nb_points();
104  }
105 
106  std::vector< index_t > get_neighbors(
107  const vecn< DIMENSION >& v, index_t nb_neighbors ) const
108  {
109  std::vector< index_t > result;
110  if( nb_points() != 0 )
111  {
112  nb_neighbors = std::min( nb_neighbors, nb_points() );
113  std::vector< double > distances( nb_neighbors );
114  result.resize( nb_neighbors );
115  nn_tree_->get_nearest_neighbors(
116  nb_neighbors, v.data(), &result[0], &distances[0] );
117  }
118  return result;
119  }
120 
121  private:
123  GEO::NearestNeighborSearch_var nn_tree_;
125  double* nn_points_;
132  };
133 
134  template < index_t DIMENSION >
136  const std::vector< vecn< DIMENSION > >& vertices, bool copy )
137  : impl_( vertices, copy )
138  {
139  }
140 
141  template < index_t DIMENSION >
143  {
144  return impl_->point( v );
145  }
146 
147  template < index_t DIMENSION >
149  {
150  return impl_->nb_points();
151  }
152 
153  template < index_t DIMENSION >
154  std::tuple< index_t, std::vector< index_t > >
156  double epsilon ) const
157  {
158  std::vector< index_t > index_map( nb_points() );
159  std::atomic< index_t > nb_colocalised_vertices{ 0 };
160  parallel_for( nb_points(), [this, &index_map, &nb_colocalised_vertices,
161  &epsilon]( index_t i ) {
162  auto results = get_neighbors( point( i ), epsilon );
163  index_t id{ *std::min_element( results.begin(), results.end() ) };
164  index_map[i] = id;
165  if( id < i )
166  {
167  nb_colocalised_vertices++;
168  }
169  } );
170  return std::make_tuple( nb_colocalised_vertices.load(), index_map );
171  }
172 
173  template < index_t DIMENSION >
174  std::tuple< index_t,
175  std::vector< index_t >,
176  std::vector< vecn< DIMENSION > > >
178  double epsilon ) const
179  {
180  index_t nb_colocalised_vertices;
181  std::vector< index_t > index_map;
182  std::tie( nb_colocalised_vertices, index_map ) =
183  get_colocated_index_mapping( epsilon );
184  std::vector< vecn< DIMENSION > > unique_points;
185  unique_points.reserve( nb_points() - nb_colocalised_vertices );
186  index_t offset{ 0 };
187  for( auto p : range( index_map.size() ) )
188  {
189  if( index_map[p] == p )
190  {
191  unique_points.push_back( point( p ) );
192  index_map[p] = p - offset;
193  }
194  else
195  {
196  offset++;
197  index_map[p] = index_map[index_map[p]];
198  }
199  }
200  ringmesh_assert( offset == nb_colocalised_vertices );
201  return std::make_tuple( offset, index_map, unique_points );
202  }
203 
204  template < index_t DIMENSION >
205  std::vector< index_t > NNSearch< DIMENSION >::get_neighbors(
206  const vecn< DIMENSION >& v, double threshold_distance ) const
207  {
208  double threshold_distance_sq{ threshold_distance * threshold_distance };
209  return get_neighbors(
210  v, [this, &v, threshold_distance_sq]( index_t i ) {
211  return length2( v - point( i ) ) > threshold_distance_sq;
212  } );
213  }
214 
215  template < index_t DIMENSION >
216  std::vector< index_t > NNSearch< DIMENSION >::get_neighbors(
217  const vecn< DIMENSION >& v, index_t nb_neighbors ) const
218  {
219  return impl_->get_neighbors( v, nb_neighbors );
220  }
221 
222  template class RINGMESH_API NNSearch< 2 >;
223  template class RINGMESH_API EXPORT_IMPLEMENTATION( NNSearch< 2 > );
224 
225  template class RINGMESH_API NNSearch< 3 >;
226  template class RINGMESH_API EXPORT_IMPLEMENTATION( NNSearch< 3 > );
227 } // namespace RINGMesh
GEO::vecng< DIMENSION, double > vecn
Definition: types.h:74
index_t nb_points() const
Definition: nn_search.cpp:101
Impl(const std::vector< vecn< DIMENSION > > &vertices, bool copy)
Definition: nn_search.cpp:55
vecn< DIMENSION > point(index_t v) const
Definition: nn_search.cpp:91
void fill_nn_search_points(index_t index_in_nn_search, const vecn< DIMENSION > &center)
Definition: nn_search.cpp:82
bool delete_points_
Indicates if ann_points_ should be deleted.
Definition: nn_search.cpp:131
GEO::NearestNeighborSearch_var nn_tree_
KdTree to compute the nearest neighbor search.
Definition: nn_search.cpp:123
double * nn_points_
Array of the points (size of DIMENSIONxnumber of points)
Definition: nn_search.cpp:125
template class RINGMESH_API EXPORT_IMPLEMENTATION(NNSearch< 2 >)
index_t nb_points() const
Definition: nn_search.cpp:148
NNSearch(const std::vector< vecn< DIMENSION > > &vertices, bool copy=true)
Definition: nn_search.cpp:135
#define ringmesh_assert(x)
vecn< DIMENSION > point(index_t v) const
Definition: nn_search.cpp:142
std::vector< index_t > get_neighbors(const vecn< DIMENSION > &v, index_t nb_neighbors) const
Definition: nn_search.cpp:106
Classes to build GeoModel from various inputs.
Definition: algorithm.h:48
std::vector< index_t > get_neighbors(const vecn< DIMENSION > &v, double threshold_distance) const
Definition: nn_search.cpp:205
std::tuple< index_t, std::vector< index_t > > get_colocated_index_mapping(double epsilon) const
Gets the index_map that link all the duplicated points to their first occurancy.
Definition: nn_search.cpp:155
std::tuple< index_t, std::vector< index_t >, std::vector< vecn< DIMENSION > > > get_colocated_index_mapping_and_unique_points(double epsilon) const
Gets the index_map that link all the points to a no duplicated list of index in the list of unique_po...
Definition: nn_search.cpp:177
void parallel_for(index_t size, const ACTION &action)
Definition: common.h:244