PointLocator.h
1 /*
2  * Medical Image Registration ToolKit (MIRTK)
3  *
4  * Copyright 2013-2015 Imperial College London
5  * Copyright 2013-2015 Andreas Schuh
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 
20 #ifndef MIRTK_PointLocator_H
21 #define MIRTK_PointLocator_H
22 
23 #include "mirtk/Object.h"
24 
25 #include "mirtk/Array.h"
26 #include "mirtk/Point.h"
27 #include "mirtk/Memory.h"
28 
29 #include "vtkSmartPointer.h"
30 #include "vtkPointSet.h"
31 #include "vtkPointData.h"
32 #include "vtkDataArray.h"
33 
34 
35 // Forward declaration of implementation using VTK point locator
36 class vtkOctreePointLocator;
37 
38 
39 namespace mirtk {
40 
41 
42 // Forward declaration of implementation using FLANN (if available)
43 class FlannPointLocator;
44 
45 
46 /**
47  * Point search structure for establishing point correspondences
48  *
49  * This point locator implementation is specialized for use by
50  * PointCorrespondence subclass implementations. It allows the search of
51  * nearest neighbors within the n-dimensional feature space spanned by the
52  * feature arrays used to establish point correspondences.
53  *
54  * The implementation uses either VTK for point search in three dimensions or
55  * FLANN for higher dimensional feature spaces if available. Alternatively,
56  * an ITK Kd tree is used if the library is available. As last resort, a brute
57  * force search without actual Kd tree search structure is performed.
58  *
59  * \todo Consider actual implementation of own thread-safe N-dimensional Kd tree?
60  *
61  * \attention When only a subset of the points is used, i.e., an index array
62  * of point set samples is given (_Sample attribute), the indices
63  * returned by this locator are the respective closest sample
64  * indices into this sample point index array. Set the _GlobalIndices
65  * flag to enable the internal mapping of closest sample indices to
66  * global point indices.
67  */
68 class PointLocator : public Object
69 {
70  mirtkObjectMacro(PointLocator);
71 
72  // ---------------------------------------------------------------------------
73  // Feature Arrays
74 public:
75 
76  /// Type storing name and/or index of point feature together with
77  /// an optional linear rescaling function
78  struct FeatureInfo
79  {
80  string _Name; ///< Name of feature/point data array
81  int _Index; ///< Index of feature/point data array
82  double _Weight; ///< Weight of feature/point data
83  double _Slope; ///< Rescaling slope of feature/point data
84  double _Intercept; ///< Rescaling intercept of feature/point data
85 
86  /// Constructor
87  FeatureInfo(int index = -2, double weight = 1.0, double slope = 1.0, double intercept = .0)
88  :
89  _Name(""), _Index(index), _Weight(weight), _Slope(slope), _Intercept(intercept)
90  {}
91 
92  /// Constructor
93  FeatureInfo(const char *name, double weight = 1.0, double slope = 1.0, double intercept = .0)
94  :
95  _Name(name), _Index(-2), _Weight(weight), _Slope(slope), _Intercept(intercept)
96  {}
97 
98  /// Constructor
99  FeatureInfo(const string &name, double weight = 1.0, double slope = 1.0, double intercept = .0)
100  :
101  _Name(name), _Index(-2), _Weight(weight), _Slope(slope), _Intercept(intercept)
102  {}
103 
104  /// Constructor
105  FeatureInfo(const char *name, int index, double weight = 1.0, double slope = 1.0, double intercept = .0)
106  :
107  _Name(name), _Index(index), _Weight(weight), _Slope(slope), _Intercept(intercept)
108  {}
109 
110  /// Constructor
111  FeatureInfo(const string &name, int index, double weight = 1.0, double slope = 1.0, double intercept = .0)
112  :
113  _Name(name), _Index(index), _Weight(weight), _Slope(slope), _Intercept(intercept)
114  {}
115  };
116 
117  /// List of point features to use for nearest neighbor search
118  typedef Array<FeatureInfo> FeatureList;
119 
120  /// Get point data array
121  ///
122  /// \param[in] dataset Dataset.
123  /// \param[in] feature Index/name and weight/rescaling parameters.
124  ///
125  /// \returns Pointer to point data array of dataset or NULL.
126  static vtkDataArray *GetDataArray(vtkPointSet *dataset, const FeatureInfo &feature);
127 
128  /// Get number of points
129  ///
130  /// \param[in] dataset Dataset.
131  /// \param[in] sample Indices of points in \p dataset to consider only or NULL for all.
132  ///
133  /// \returns Number of (sample) points.
134  static int GetNumberOfPoints(vtkPointSet *dataset, const Array<int> *sample = NULL);
135 
136  /// Get size of feature Arrays
137  ///
138  /// \param[in] dataset Dataset.
139  /// \param[in] feature Indices/names and weights/rescaling parameters of features.
140  static int GetPointDimension(vtkPointSet *dataset, const FeatureList *feature);
141 
142  /// Get index of feature Array
143  ///
144  /// \param[in] dataset Dataset.
145  /// \param[in] sample Indices of points in \p dataset to consider only or NULL for all.
146  /// \param[in] index Index of point in \p dataset or \p sample (if not NULL).
147  ///
148  /// \returns Index of feature Array/point in \p dataset.
149  static int GetPointIndex(vtkPointSet *dataset, const Array<int> *sample, int index);
150 
151  /// Get spatial (sample) point
152  ///
153  /// \param[out] point Spatial point.
154  /// \param[in] dataset Dataset.
155  /// \param[in] sample Indices of points in \p dataset to consider only or NULL for all.
156  /// \param[in] index Index of point in \p dataset or \p sample (if not NULL).
157  static void GetPoint(Point &point, vtkPointSet *dataset, const Array<int> *sample, int index);
158 
159  /// Get feature Array
160  ///
161  /// \param[out] point Feature Array.
162  /// \param[in] dataset Dataset.
163  /// \param[in] sample Indices of points in \p dataset to consider only or NULL for all.
164  /// \param[in] index Index of point in \p dataset or \p sample (if not NULL).
165  /// \param[in] feature Indices/names and weights/rescaling parameters of features.
166  static void GetPoint(double *point, vtkPointSet *dataset, const Array<int> *sample,
167  int index, const FeatureList *feature = NULL);
168 
169  /// Get feature Array
170  ///
171  /// \param[out] point Feature Array.
172  /// \param[in] dataset Dataset.
173  /// \param[in] index Index of point in \p dataset.
174  /// \param[in] feature Indices/names and weights/rescaling parameters of features.
175  static void GetPoint(double *point, vtkPointSet *dataset, int index, const FeatureList *feature = NULL);
176 
177  /// Calculate squared Euclidean distance between feature Arrays
178  ///
179  /// \param[in] a First feature Array.
180  /// \param[in] b Second feature Array.
181  /// \param[in] d Dimension of feature Arrays.
182  ///
183  /// \returns Squared Euclidean distance, i.e., dot product of a and b.
184  static double Distance2BetweenPoints(const double *a, const double *b, int d = 3);
185 
186  // ---------------------------------------------------------------------------
187  // Attributes
188 
189  /// Dataset for which search structure is build
190  mirtkPublicAggregateMacro(vtkPointSet, DataSet);
191 
192  /// Indices of points to consider only or NULL
193  mirtkPublicAggregateMacro(const Array<int>, Sample);
194 
195  /// Indices/names and rescaling parameters of point data arrays
196  mirtkPublicAttributeMacro(FeatureList, Features);
197 
198  /// Return global _DataSet point indices instead of _Sample indices
199  mirtkPublicAttributeMacro(bool, GlobalIndices);
200 
201  /// Number of points in search structure
203 
204  /// Dimension of feature Arrays/points
205  mirtkReadOnlyAttributeMacro(int, PointDimension);
206 
207  /// VTK point locator used for three-dimensional feature spaces
208  vtkSmartPointer<vtkOctreePointLocator> _VtkLocator;
209 
210  /// FLANN point locator used for higher-dimensional feature spaces when available
211  SharedPtr<FlannPointLocator> _FlannLocator;
212 
213  // ---------------------------------------------------------------------------
214  // Construction/Destruction
215 
216 protected:
217 
218  /// Constructor
219  PointLocator();
220 
221  /// Initialize point locator
222  void Initialize();
223 
224 private:
225 
226  /// Copy constructor
227  /// \note Intentionally not implemented
228  PointLocator(const PointLocator &);
229 
230  /// Assignment operator
231  /// \note Intentionally not implemented
232  void operator =(const PointLocator &);
233 
234 public:
235 
236  /// Construct new point locator for search in given dataset
237  ///
238  /// \param[in] dataset Dataset in which points are searched.
239  /// \param[in] sample Indices of points in \p dataset to consider only or NULL for all.
240  /// \param[in] feature Indices and weights of point data in \p dataset to use.
241  static PointLocator *New(vtkPointSet *dataset,
242  const Array<int> *sample = NULL,
243  const FeatureList *feature = NULL);
244 
245  /// Destructor
246  virtual ~PointLocator();
247 
248  // ---------------------------------------------------------------------------
249  // Closest point
250 
251  /// Find closest point
252  ///
253  /// \param[in] point Query point.
254  /// \param[out] dist2 Squared Euclidean distance of closest point.
255  ///
256  /// \returns Index of point/sample in dataset closest to the query \p point.
257  int FindClosestPoint(double *point, double *dist2 = NULL);
258 
259  /// Find closest point
260  ///
261  /// \param[in] dataset Dataset whose nearest neighbor is queried.
262  /// \param[in] sample Indices of points in \p dataset to consider only or NULL for all.
263  /// \param[in] index Index of point in \p dataset or \p sample (if not NULL).
264  /// \param[in] features Indices and weights of point data in \p dataset to use.
265  /// \param[out] dist2 Squared Euclidean distance of closest point.
266  ///
267  /// \returns Index of point/sample in dataset closest to the i-th point in \p dataset.
268  int FindClosestPoint(vtkPointSet *dataset,
269  const Array<int> *sample,
270  int index,
271  const FeatureList *features,
272  double *dist2 = NULL);
273 
274  /// Find closest point
275  ///
276  /// \param[in] dataset Dataset whose nearest neighbor is queried.
277  /// \param[in] index Index of point in \p dataset or \p sample (if not NULL).
278  /// \param[in] features Indices and weights of point data in \p dataset to use.
279  /// \param[out] dist2 Squared Euclidean distance of closest point.
280  ///
281  /// \returns Index of point/sample in dataset closest to the i-th point in \p dataset.
282  int FindClosestPoint(vtkPointSet *dataset,
283  int index,
284  const FeatureList *features,
285  double *dist2 = NULL);
286 
287  /// Find closest point
288  ///
289  /// \param[in] dataset Dataset whose nearest neighbor is queried.
290  /// \param[in] sample Indices of points in \p dataset to consider only or NULL for all.
291  /// \param[in] index Index of point in \p dataset or \p sample (if not NULL).
292  /// \param[out] dist2 Squared Euclidean distance of closest point.
293  ///
294  /// \returns Index of point/sample in dataset closest to the i-th point in \p dataset.
295  int FindClosestPoint(vtkPointSet *dataset,
296  const Array<int> *sample,
297  int index,
298  double *dist2 = NULL);
299 
300  /// Find closest point
301  ///
302  /// \param[in] dataset Dataset whose nearest neighbor is queried.
303  /// \param[in] index Index of point in \p dataset.
304  /// \param[out] dist2 Squared Euclidean distance of closest point.
305  ///
306  /// \returns Index of point/sample in dataset closest to the i-th point in \p dataset.
307  int FindClosestPoint(vtkPointSet *dataset,
308  int index,
309  double *dist2 = NULL);
310 
311  /// Find closest point
312  ///
313  /// \param[in] dataset Dataset whose nearest neighbor is queried.
314  /// \param[in] sample Indices of points in \p dataset to consider only or NULL for all.
315  /// \param[in] features Indices and weights of point data in \p dataset to use.
316  /// \param[out] dist2 Squared Euclidean distance of closest point.
317  ///
318  /// \returns Indices of points/samples closest to each point in \p dataset.
319  Array<int> FindClosestPoint(vtkPointSet *dataset,
320  const Array<int> *sample,
321  const FeatureList *features,
322  Array<double> *dist2 = NULL);
323 
324  /// Find closest point
325  ///
326  /// \param[in] dataset Dataset whose nearest neighbor is queried.
327  /// \param[in] features Indices and weights of point data in \p dataset to use.
328  /// \param[out] dist2 Squared Euclidean distance of closest point.
329  ///
330  /// \returns Indices of points/samples closest to each point in \p dataset.
331  Array<int> FindClosestPoint(vtkPointSet *dataset,
332  const FeatureList *features,
333  Array<double> *dist2 = NULL);
334 
335  /// Find closest point
336  ///
337  /// \param[in] dataset Dataset whose nearest neighbor is queried.
338  /// \param[in] sample Indices of points in \p dataset to consider only or NULL for all.
339  /// \param[out] dist2 Squared Euclidean distance of closest point.
340  ///
341  /// \returns Indices of points/samples closest to each point in \p dataset.
342  Array<int> FindClosestPoint(vtkPointSet *dataset,
343  const Array<int> *sample,
344  Array<double> *dist2 = NULL);
345 
346  /// Find closest point
347  ///
348  /// \param[in] dataset Dataset whose nearest neighbor is queried.
349  /// \param[out] dist2 Squared Euclidean distance of closest point.
350  ///
351  /// \returns Indices of points/samples closest to each point in \p dataset.
352  Array<int> FindClosestPoint(vtkPointSet *dataset,
353  Array<double> *dist2 = NULL);
354 
355  /// Find closest point
356  ///
357  /// \param[in] dataset1 Dataset whose nearest neighbor is queried.
358  /// \param[in] sample1 Indices of points in \p dataset1 to consider only or NULL for all.
359  /// \param[in] features1 Indices and weights of point data in \p dataset1 to use.
360  /// \param[in] dataset2 Dataset in which to perform nearest neighbor search.
361  /// \param[in] sample2 Indices of points in \p dataset2 to consider only or NULL for all.
362  /// \param[in] features2 Indices and weights of point data in \p dataset2 to use.
363  /// \param[out] dist2 Squared Euclidean distance of closest point.
364  ///
365  /// \returns Indices of points/samples in \p dataset2 which are closest to each point in \p dataset1.
366  static Array<int> FindClosestPoint(vtkPointSet *dataset1,
367  const Array<int> *sample1,
368  const FeatureList *features1,
369  vtkPointSet *dataset2,
370  const Array<int> *sample2,
371  const FeatureList *features2,
372  Array<double> *dist2 = NULL);
373 
374  // ---------------------------------------------------------------------------
375  // Nearest neighbors (kNN)
376 
377  /// Find k nearest neighbors
378  ///
379  /// \param[in] k Number of nearest neighbors to find.
380  /// \param[in] point Query point.
381  /// \param[out] dist2 Squared Euclidean distance of closest point.
382  ///
383  /// \returns Indices of points in dataset closests to the i-th point in \p d.
384  Array<int> FindClosestNPoints(int k, double *point, Array<double> *dist2 = NULL);
385 
386  /// Find k nearest neighbors
387  ///
388  /// \param[in] k Number of nearest neighbors to find.
389  /// \param[in] dataset Dataset whose nearest neighbors are queried.
390  /// \param[in] sample Indices of points in \p dataset to consider only or NULL for all.
391  /// \param[in] index Index of point in \p dataset or \p sample (if not NULL).
392  /// \param[in] features Indices and weights of point data in \p dataset to use.
393  /// \param[out] dist2 Squared Euclidean distance of found nearest neighbors.
394  ///
395  /// \returns Indices of points in dataset closests to the i-th point in \p d.
396  Array<int> FindClosestNPoints(int k, vtkPointSet *dataset,
397  const Array<int> *sample,
398  int index,
399  const FeatureList *features,
400  Array<double> *dist2 = NULL);
401 
402  /// Find k nearest neighbors
403  ///
404  /// \param[in] k Number of nearest neighbors to find.
405  /// \param[in] dataset Dataset whose nearest neighbors are queried.
406  /// \param[in] sample Indices of points in \p dataset to consider only or NULL for all.
407  /// \param[in] index Index of point in \p dataset or \p sample (if not NULL).
408  /// \param[out] dist2 Squared Euclidean distance of found nearest neighbors.
409  ///
410  /// \returns Indices of points in dataset closests to the i-th point in \p d.
411  Array<int> FindClosestNPoints(int k, vtkPointSet *dataset,
412  const Array<int> *sample,
413  int index,
414  Array<double> *dist2 = NULL);
415 
416  /// Find k nearest neighbors
417  ///
418  /// \param[in] k Number of nearest neighbors to find.
419  /// \param[in] dataset Dataset whose nearest neighbors are queried.
420  /// \param[in] index Index of point in \p dataset.
421  /// \param[in] features Indices and weights of point data in \p dataset to use.
422  /// \param[out] dist2 Squared Euclidean distance of found nearest neighbors.
423  ///
424  /// \returns Indices of points in dataset closests to the i-th point in \p d.
425  Array<int> FindClosestNPoints(int k, vtkPointSet *dataset,
426  int index,
427  const FeatureList *features,
428  Array<double> *dist2 = NULL);
429 
430  /// Find k nearest neighbors
431  ///
432  /// \param[in] k Number of nearest neighbors to find.
433  /// \param[in] dataset Dataset whose nearest neighbors are queried.
434  /// \param[in] index Index of point in \p dataset.
435  /// \param[out] dist2 Squared Euclidean distance of found nearest neighbors.
436  ///
437  /// \returns Indices of points in dataset closests to the i-th point in \p d.
438  Array<int> FindClosestNPoints(int k, vtkPointSet *dataset, int index,
439  Array<double> *dist2 = NULL);
440 
441  /// Find k nearest neighbors
442  ///
443  /// \param[in] k Number of nearest neighbors to find.
444  /// \param[in] dataset Dataset whose nearest neighbors are queried.
445  /// \param[in] sample Indices of points in \p dataset to consider only or NULL for all.
446  /// \param[in] features Indices and weights of point data in \p dataset to use.
447  /// \param[out] dist2 Squared Euclidean distance of found nearest neighbors.
448  ///
449  /// \returns For each point in \p dataset, indices of closest \p k points.
450  Array<Array<int> > FindClosestNPoints(int k, vtkPointSet *dataset,
451  const Array<int> *sample,
452  const FeatureList *features,
453  Array<Array<double> > *dist2 = NULL);
454 
455  /// Find k nearest neighbors
456  ///
457  /// \param[in] k Number of nearest neighbors to find.
458  /// \param[in] dataset Dataset whose nearest neighbors are queried.
459  /// \param[in] sample Indices of points in \p dataset to consider only or NULL for all.
460  /// \param[out] dist2 Squared Euclidean distance of found nearest neighbors.
461  ///
462  /// \returns For each point in \p dataset, indices of closest \p k points.
463  Array<Array<int> > FindClosestNPoints(int k, vtkPointSet *dataset,
464  const Array<int> *sample,
465  Array<Array<double> > *dist2 = NULL);
466 
467  /// Find k nearest neighbors
468  ///
469  /// \param[in] k Number of nearest neighbors to find.
470  /// \param[in] dataset Dataset whose nearest neighbors are queried.
471  /// \param[in] features Indices and weights of point data in \p dataset to use.
472  /// \param[out] dist2 Squared Euclidean distance of found nearest neighbors.
473  ///
474  /// \returns For each point in \p dataset, indices of closest \p k points.
475  Array<Array<int> > FindClosestNPoints(int k, vtkPointSet *dataset,
476  const FeatureList *features,
477  Array<Array<double> > *dist2 = NULL);
478 
479  /// Find k nearest neighbors
480  ///
481  /// \param[in] k Number of nearest neighbors to find.
482  /// \param[in] dataset Dataset whose nearest neighbors are queried.
483  /// \param[out] dist2 Squared Euclidean distance of found nearest neighbors.
484  ///
485  /// \returns For each point in \p dataset, indices of closest \p k points.
486  Array<Array<int> > FindClosestNPoints(int k, vtkPointSet *dataset,
487  Array<Array<double> > *dist2 = NULL);
488 
489  /// Find k nearest neighbors
490  ///
491  /// \param[in] k Number of nearest neighbors to find.
492  /// \param[in] dataset1 Dataset whose nearest neighbor is queried.
493  /// \param[in] sample1 Indices of points in \p dataset1 to consider only or NULL for all.
494  /// \param[in] features1 Indices and weights of point data in \p dataset1 to use.
495  /// \param[in] dataset2 Dataset in which to perform nearest neighbor search.
496  /// \param[in] sample2 Indices of points in \p dataset2 to consider only or NULL for all.
497  /// \param[in] features2 Indices and weights of point data in \p dataset2 to use.
498  /// \param[out] dist2 Squared Euclidean distance of closest point.
499  ///
500  /// \returns For each point in \p dataset1, indices of closest \p k points in \p dataset2.
501  static Array<Array<int> > FindClosestNPoints(int k,
502  vtkPointSet *dataset1,
503  const Array<int> *sample1,
504  const FeatureList *features1,
505  vtkPointSet *dataset2,
506  const Array<int> *sample2,
507  const FeatureList *features2,
508  Array<Array<double> > *dist2 = NULL);
509 
510  // ---------------------------------------------------------------------------
511  // Radius search
512 
513  /// Find neighbors within search radius
514  ///
515  /// \param[in] radius Search radius in N-D point feature space.
516  /// \param[in] point Query point.
517  /// \param[out] dist2 Squared Euclidean distance of closest point.
518  ///
519  /// \returns Indices of points in dataset closests to the i-th point in \p d.
520  Array<int> FindPointsWithinRadius(double radius, double *point, Array<double> *dist2 = NULL);
521 
522  /// Find neighbors within search radius
523  ///
524  /// \param[in] radius Search radius in N-D point feature space.
525  /// \param[in] dataset Dataset whose nearest neighbors are queried.
526  /// \param[in] sample Indices of points in \p dataset to consider only or NULL for all.
527  /// \param[in] index Index of point in \p dataset or \p sample (if not NULL).
528  /// \param[in] features Indices and weights of point data in \p dataset to use.
529  /// \param[out] dist2 Squared Euclidean distance of found nearest neighbors.
530  ///
531  /// \returns Indices of points in dataset closests to the i-th point in \p d.
532  Array<int> FindPointsWithinRadius(double radius, vtkPointSet *dataset,
533  const Array<int> *sample,
534  int index,
535  const FeatureList *features,
536  Array<double> *dist2 = NULL);
537 
538  /// Find neighbors within search radius
539  ///
540  /// \param[in] radius Search radius in N-D point feature space.
541  /// \param[in] dataset Dataset whose nearest neighbors are queried.
542  /// \param[in] sample Indices of points in \p dataset to consider only or NULL for all.
543  /// \param[in] index Index of point in \p dataset or \p sample (if not NULL).
544  /// \param[out] dist2 Squared Euclidean distance of found nearest neighbors.
545  ///
546  /// \returns Indices of points in dataset closests to the i-th point in \p d.
547  Array<int> FindPointsWithinRadius(double radius, vtkPointSet *dataset,
548  const Array<int> *sample,
549  int index,
550  Array<double> *dist2 = NULL);
551 
552  /// Find neighbors within search radius
553  ///
554  /// \param[in] radius Search radius in N-D point feature space.
555  /// \param[in] dataset Dataset whose nearest neighbors are queried.
556  /// \param[in] index Index of point in \p dataset.
557  /// \param[in] features Indices and weights of point data in \p dataset to use.
558  /// \param[out] dist2 Squared Euclidean distance of found nearest neighbors.
559  ///
560  /// \returns Indices of points in dataset closests to the i-th point in \p d.
561  Array<int> FindPointsWithinRadius(double radius, vtkPointSet *dataset,
562  int index,
563  const FeatureList *features,
564  Array<double> *dist2 = NULL);
565 
566  /// Find neighbors within search radius
567  ///
568  /// \param[in] radius Search radius in N-D point feature space.
569  /// \param[in] dataset Dataset whose nearest neighbors are queried.
570  /// \param[in] index Index of point in \p dataset.
571  /// \param[out] dist2 Squared Euclidean distance of found nearest neighbors.
572  ///
573  /// \returns Indices of points in dataset closests to the i-th point in \p d.
574  Array<int> FindPointsWithinRadius(double radius, vtkPointSet *dataset, int index,
575  Array<double> *dist2 = NULL);
576 
577  /// Find neighbors within search radius
578  ///
579  /// \param[in] radius Search radius in N-D point feature space.
580  /// \param[in] dataset Dataset whose nearest neighbors are queried.
581  /// \param[in] sample Indices of points in \p dataset to consider only or NULL for all.
582  /// \param[in] features Indices and weights of point data in \p dataset to use.
583  /// \param[out] dist2 Squared Euclidean distance of found nearest neighbors.
584  ///
585  /// \returns For each point in \p dataset, indices of points within search \p radius.
586  Array<Array<int> > FindPointsWithinRadius(double radius, vtkPointSet *dataset,
587  const Array<int> *sample,
588  const FeatureList *features,
589  Array<Array<double> > *dist2 = NULL);
590 
591  /// Find neighbors within search radius
592  ///
593  /// \param[in] radius Search radius in N-D point feature space.
594  /// \param[in] dataset Dataset whose nearest neighbors are queried.
595  /// \param[in] sample Indices of points in \p dataset to consider only or NULL for all.
596  /// \param[out] dist2 Squared Euclidean distance of found nearest neighbors.
597  ///
598  /// \returns For each point in \p dataset, indices of points within search \p radius.
599  Array<Array<int> > FindPointsWithinRadius(double radius, vtkPointSet *dataset,
600  const Array<int> *sample,
601  Array<Array<double> > *dist2 = NULL);
602 
603  /// Find neighbors within search radius
604  ///
605  /// \param[in] radius Search radius in N-D point feature space.
606  /// \param[in] dataset Dataset whose nearest neighbors are queried.
607  /// \param[in] features Indices and weights of point data in \p dataset to use.
608  /// \param[out] dist2 Squared Euclidean distance of found nearest neighbors.
609  ///
610  /// \returns For each point in \p dataset, indices of points within search \p radius.
611  Array<Array<int> > FindPointsWithinRadius(double radius, vtkPointSet *dataset,
612  const FeatureList *features,
613  Array<Array<double> > *dist2 = NULL);
614 
615  /// Find neighbors within search radius
616  ///
617  /// \param[in] radius Search radius in N-D point feature space.
618  /// \param[in] dataset Dataset whose nearest neighbors are queried.
619  /// \param[out] dist2 Squared Euclidean distance of found nearest neighbors.
620  ///
621  /// \returns For each point in \p dataset, indices of points within search \p radius.
622  Array<Array<int> > FindPointsWithinRadius(double radius, vtkPointSet *dataset,
623  Array<Array<double> > *dist2 = NULL);
624 
625  /// Find neighbors within search radius
626  ///
627  /// \param[in] radius Search radius in N-D point feature space.
628  /// \param[in] dataset1 Dataset whose nearest neighbor is queried.
629  /// \param[in] sample1 Indices of points in \p dataset1 to consider only or NULL for all.
630  /// \param[in] features1 Indices and weights of point data in \p dataset1 to use.
631  /// \param[in] dataset2 Dataset in which to perform nearest neighbor search.
632  /// \param[in] sample2 Indices of points in \p dataset2 to consider only or NULL for all.
633  /// \param[in] features2 Indices and weights of point data in \p dataset2 to use.
634  /// \param[out] dist2 Squared Euclidean distance of closest point.
635  ///
636  /// \returns For each point in \p dataset1, indices of points in \p dataset2 within search \p radius.
637  static Array<Array<int> > FindPointsWithinRadius(double radius,
638  vtkPointSet *dataset1,
639  const Array<int> *sample1,
640  const FeatureList *features1,
641  vtkPointSet *dataset2,
642  const Array<int> *sample2,
643  const FeatureList *features2,
644  Array<Array<double> > *dist2 = NULL);
645 
646 };
647 
648 ////////////////////////////////////////////////////////////////////////////////
649 // Inline definitions
650 ////////////////////////////////////////////////////////////////////////////////
651 
652 // =============================================================================
653 // Static helpers
654 // =============================================================================
655 
656 // -----------------------------------------------------------------------------
657 inline vtkDataArray *PointLocator::GetDataArray(vtkPointSet *dataset, const FeatureInfo &feature)
658 {
659  vtkPointData * const pd = dataset->GetPointData();
660  if (feature._Index >= 0) return pd->GetArray(feature._Index);
661  return pd->GetArray(feature._Name.c_str());
662 }
663 
664 // -----------------------------------------------------------------------------
665 inline int PointLocator::GetNumberOfPoints(vtkPointSet *dataset, const Array<int> *sample)
666 {
667  return (sample && sample->size() > 0 ? static_cast<int>(sample->size()) : dataset->GetNumberOfPoints());
668 }
669 
670 // -----------------------------------------------------------------------------
671 inline int PointLocator::GetPointDimension(vtkPointSet *dataset, const FeatureList *features)
672 {
673  int dim;
674  if (features && features->size() > 0) {
675  dim = 0;
676  vtkDataArray *feature_array;
677  for (FeatureList::const_iterator feature = features->begin(); feature != features->end(); ++feature) {
678  if (feature->_Weight != .0) {
679  if (feature->_Index == -1) {
680  dim += 3;
681  } else {
682  feature_array = GetDataArray(dataset, *feature);
683  dim += feature_array->GetNumberOfComponents();
684  }
685  }
686  }
687  } else {
688  dim = 3;
689  }
690  return dim;
691 }
692 
693 // -----------------------------------------------------------------------------
694 inline int PointLocator::GetPointIndex(vtkPointSet *dataset, const Array<int> *sample, int index)
695 {
696  return (sample && sample->size() > 0 ? (*sample)[index] : index);
697 }
698 
699 // -----------------------------------------------------------------------------
700 inline void PointLocator
701 ::GetPoint(Point &point, vtkPointSet *dataset, const Array<int> *sample, int index)
702 {
703  double pt[3];
704  const int i = GetPointIndex(dataset, sample, index);
705  dataset->GetPoint(i, pt);
706  point._x = pt[0], point._y = pt[1], point._z = pt[2];
707 }
708 
709 // -----------------------------------------------------------------------------
710 inline void PointLocator
711 ::GetPoint(double *point, vtkPointSet *dataset, const Array<int> *sample, int index, const FeatureList *features)
712 {
713  const int i = GetPointIndex(dataset, sample, index);
714  if (features && features->size() > 0) {
715  vtkDataArray *feature_array;
716  for (FeatureList::const_iterator feature = features->begin(); feature != features->end(); ++feature) {
717  if (feature->_Weight != .0) {
718  if (feature->_Index == -1) {
719  dataset->GetPoint(i, point);
720  for (int d = 0; d < 3; ++d, ++point) {
721  (*point) = feature->_Weight * (feature->_Slope * (*point) + feature->_Intercept);
722  }
723  } else {
724  feature_array = GetDataArray(dataset, *feature);
725  feature_array->GetTuple(i, point);
726  for (int d = 0; d < feature_array->GetNumberOfComponents(); ++d, ++point) {
727  (*point) = feature->_Weight * (feature->_Slope * (*point) + feature->_Intercept);
728  }
729  }
730  }
731  }
732  } else {
733  dataset->GetPoint(i, point);
734  }
735 }
736 
737 // -----------------------------------------------------------------------------
738 inline void PointLocator
739 ::GetPoint(double *point, vtkPointSet *dataset, int index, const FeatureList *features)
740 {
741  GetPoint(point, dataset, NULL, index, features);
742 }
743 
744 // -----------------------------------------------------------------------------
745 inline double PointLocator
746 ::Distance2BetweenPoints(const double *a, const double *b, int d)
747 {
748  double dx, dist2 = .0;
749  for (int i = 0; i < d; ++i) {
750  dx = b[i] - a[i];
751  dist2 += dx * dx;
752  }
753  return dist2;
754 }
755 
756 // =============================================================================
757 // Closest point
758 // =============================================================================
759 
760 // -----------------------------------------------------------------------------
761 inline int PointLocator
762 ::FindClosestPoint(vtkPointSet *dataset, const Array<int> *sample, int index,
763  const FeatureList *features, double *dist2)
764 {
765  double *point = new double[_PointDimension];
766  GetPoint(point, dataset, sample, index, features);
767  int i = this->FindClosestPoint(point, dist2);
768  delete[] point;
769  return i;
770 }
771 
772 // -----------------------------------------------------------------------------
773 inline int PointLocator
774 ::FindClosestPoint(vtkPointSet *dataset, int index,
775  const FeatureList *features, double *dist2)
776 {
777  return FindClosestPoint(dataset, NULL, index, features, dist2);
778 }
779 
780 // -----------------------------------------------------------------------------
781 inline int PointLocator
782 ::FindClosestPoint(vtkPointSet *dataset, const Array<int> *sample,
783  int index, double *dist2)
784 {
785  return FindClosestPoint(dataset, sample, index, NULL, dist2);
786 }
787 
788 // -----------------------------------------------------------------------------
789 inline int PointLocator
790 ::FindClosestPoint(vtkPointSet *dataset, int index, double *dist2)
791 {
792  return FindClosestPoint(dataset, NULL, index, dist2);
793 }
794 
795 // -----------------------------------------------------------------------------
796 inline Array<int> PointLocator
797 ::FindClosestPoint(vtkPointSet *dataset, const FeatureList *features, Array<double> *dist2)
798 {
799  return FindClosestPoint(dataset, NULL, features, dist2);
800 }
801 
802 // -----------------------------------------------------------------------------
803 inline Array<int> PointLocator
804 ::FindClosestPoint(vtkPointSet *dataset, const Array<int> *sample, Array<double> *dist2)
805 {
806  return FindClosestPoint(dataset, sample, NULL, dist2);
807 }
808 
809 // -----------------------------------------------------------------------------
810 inline Array<int> PointLocator
811 ::FindClosestPoint(vtkPointSet *dataset, Array<double> *dist2)
812 {
813  return FindClosestPoint(dataset, NULL, NULL, dist2);
814 }
815 
816 // -----------------------------------------------------------------------------
817 inline Array<int> PointLocator
818 ::FindClosestPoint(vtkPointSet *dataset1, const Array<int> *sample1, const FeatureList *features1,
819  vtkPointSet *dataset2, const Array<int> *sample2, const FeatureList *features2,
820  Array<double> *dist2)
821 {
822  UniquePtr<PointLocator> locator(PointLocator::New(dataset2, sample2, features2));
823  return locator->FindClosestPoint(dataset1, sample1, features1, dist2);
824 }
825 
826 // =============================================================================
827 // Nearest neighbors (kNN)
828 // =============================================================================
829 
830 // -----------------------------------------------------------------------------
831 inline Array<int> PointLocator
832 ::FindClosestNPoints(int k, vtkPointSet *dataset, const Array<int> *sample, int index,
833  const FeatureList *features, Array<double> *dist2)
834 {
835  double *point = new double[_PointDimension];
836  GetPoint(point, dataset, sample, index, features);
837  Array<int> indices = this->FindClosestNPoints(k, point, dist2);
838  delete[] point;
839  return indices;
840 }
841 
842 // -----------------------------------------------------------------------------
843 inline Array<int> PointLocator
844 ::FindClosestNPoints(int k, vtkPointSet *dataset, int index,
845  const FeatureList *features, Array<double> *dist2)
846 {
847  return FindClosestNPoints(k, dataset, NULL, index, features, dist2);
848 }
849 
850 // -----------------------------------------------------------------------------
851 inline Array<int> PointLocator
852 ::FindClosestNPoints(int k, vtkPointSet *dataset, const Array<int> *sample,
853  int index, Array<double> *dist2)
854 {
855  return FindClosestNPoints(k, dataset, sample, index, NULL, dist2);
856 }
857 
858 // -----------------------------------------------------------------------------
859 inline Array<int> PointLocator
860 ::FindClosestNPoints(int k, vtkPointSet *dataset, int index, Array<double> *dist2)
861 {
862  return FindClosestNPoints(k, dataset, NULL, index, dist2);
863 }
864 
865 // -----------------------------------------------------------------------------
866 inline Array<Array<int> > PointLocator
867 ::FindClosestNPoints(int k, vtkPointSet *dataset, const FeatureList *features, Array<Array<double> > *dist2)
868 {
869  return FindClosestNPoints(k, dataset, NULL, features, dist2);
870 }
871 
872 // -----------------------------------------------------------------------------
873 inline Array<Array<int> > PointLocator
874 ::FindClosestNPoints(int k, vtkPointSet *dataset, const Array<int> *sample, Array<Array<double> > *dist2)
875 {
876  return FindClosestNPoints(k, dataset, sample, NULL, dist2);
877 }
878 
879 // -----------------------------------------------------------------------------
880 inline Array<Array<int> > PointLocator
881 ::FindClosestNPoints(int k, vtkPointSet *dataset, Array<Array<double> > *dist2)
882 {
883  return FindClosestNPoints(k, dataset, NULL, NULL, dist2);
884 }
885 
886 // -----------------------------------------------------------------------------
887 inline Array<Array<int> > PointLocator
888 ::FindClosestNPoints(int k, vtkPointSet *dataset1, const Array<int> *sample1, const FeatureList *features1,
889  vtkPointSet *dataset2, const Array<int> *sample2, const FeatureList *features2,
890  Array<Array<double> > *dist2)
891 {
892  UniquePtr<PointLocator> locator(PointLocator::New(dataset2, sample2, features2));
893  return locator->FindClosestNPoints(k, dataset1, sample1, features1, dist2);
894 }
895 
896 // =============================================================================
897 // Radius search
898 // =============================================================================
899 
900 // -----------------------------------------------------------------------------
901 inline Array<int> PointLocator
902 ::FindPointsWithinRadius(double radius, vtkPointSet *dataset, const Array<int> *sample,
903  int index, const FeatureList *features, Array<double> *dist2)
904 {
905  double *point = new double[_PointDimension];
906  GetPoint(point, dataset, sample, index, features);
907  Array<int> indices = this->FindPointsWithinRadius(radius, point, dist2);
908  delete[] point;
909  return indices;
910 }
911 
912 // -----------------------------------------------------------------------------
913 inline Array<int> PointLocator
914 ::FindPointsWithinRadius(double radius, vtkPointSet *dataset, int index,
915  const FeatureList *features, Array<double> *dist2)
916 {
917  return FindPointsWithinRadius(radius, dataset, NULL, index, features, dist2);
918 }
919 
920 // -----------------------------------------------------------------------------
921 inline Array<int> PointLocator
922 ::FindPointsWithinRadius(double radius, vtkPointSet *dataset, const Array<int> *sample,
923  int index, Array<double> *dist2)
924 {
925  return FindPointsWithinRadius(radius, dataset, sample, index, NULL, dist2);
926 }
927 
928 // -----------------------------------------------------------------------------
929 inline Array<int> PointLocator
930 ::FindPointsWithinRadius(double radius, vtkPointSet *dataset, int index, Array<double> *dist2)
931 {
932  return FindPointsWithinRadius(radius, dataset, NULL, index, dist2);
933 }
934 
935 // -----------------------------------------------------------------------------
936 inline Array<Array<int> > PointLocator
937 ::FindPointsWithinRadius(double radius, vtkPointSet *dataset,
938  const FeatureList *features, Array<Array<double> > *dist2)
939 {
940  return FindPointsWithinRadius(radius, dataset, NULL, features, dist2);
941 }
942 
943 // -----------------------------------------------------------------------------
944 inline Array<Array<int> > PointLocator
945 ::FindPointsWithinRadius(double radius, vtkPointSet *dataset, const Array<int> *sample, Array<Array<double> > *dist2)
946 {
947  return FindPointsWithinRadius(radius, dataset, sample, NULL, dist2);
948 }
949 
950 // -----------------------------------------------------------------------------
951 inline Array<Array<int> > PointLocator
952 ::FindPointsWithinRadius(double radius, vtkPointSet *dataset, Array<Array<double> > *dist2)
953 {
954  return FindPointsWithinRadius(radius, dataset, NULL, NULL, dist2);
955 }
956 
957 // -----------------------------------------------------------------------------
958 inline Array<Array<int> > PointLocator
959 ::FindPointsWithinRadius(double radius, vtkPointSet *dataset1, const Array<int> *sample1, const FeatureList *features1,
960  vtkPointSet *dataset2, const Array<int> *sample2, const FeatureList *features2,
961  Array<Array<double> > *dist2)
962 {
963  UniquePtr<PointLocator> locator(PointLocator::New(dataset2, sample2, features2));
964  return locator->FindPointsWithinRadius(radius, dataset1, sample1, features1, dist2);
965 }
966 
967 
968 } // namespace mirtk
969 
970 #endif // MIRTK_PointLocator_H
PointLocator()
Constructor.
double _Slope
Rescaling slope of feature/point data.
Definition: PointLocator.h:83
int FindClosestPoint(double *point, double *dist2=NULL)
FeatureInfo(const char *name, int index, double weight=1.0, double slope=1.0, double intercept=.0)
Constructor.
Definition: PointLocator.h:105
FeatureInfo(const string &name, double weight=1.0, double slope=1.0, double intercept=.0)
Constructor.
Definition: PointLocator.h:99
SharedPtr< FlannPointLocator > _FlannLocator
FLANN point locator used for higher-dimensional feature spaces when available.
Definition: PointLocator.h:211
double _Weight
Weight of feature/point data.
Definition: PointLocator.h:82
mirtkPublicAttributeMacro(FeatureList, Features)
Indices/names and rescaling parameters of point data arrays.
static int GetPointDimension(vtkPointSet *dataset, const FeatureList *feature)
Definition: PointLocator.h:671
double _x
x coordinate of Point
Definition: Point.h:46
int _Index
Index of feature/point data array.
Definition: PointLocator.h:81
static int GetNumberOfPoints(vtkPointSet *dataset, const Array< int > *sample=NULL)
Definition: PointLocator.h:665
FeatureInfo(const string &name, int index, double weight=1.0, double slope=1.0, double intercept=.0)
Constructor.
Definition: PointLocator.h:111
static double Distance2BetweenPoints(const double *a, const double *b, int d=3)
Definition: PointLocator.h:746
Array< FeatureInfo > FeatureList
List of point features to use for nearest neighbor search.
Definition: PointLocator.h:118
static vtkDataArray * GetDataArray(vtkPointSet *dataset, const FeatureInfo &feature)
Definition: PointLocator.h:657
virtual ~PointLocator()
Destructor.
Definition: IOConfig.h:41
Array< int > FindPointsWithinRadius(double radius, double *point, Array< double > *dist2=NULL)
mirtkReadOnlyAttributeMacro(int, NumberOfPoints)
Number of points in search structure.
void Initialize()
Initialize point locator.
static int GetPointIndex(vtkPointSet *dataset, const Array< int > *sample, int index)
Definition: PointLocator.h:694
mirtkPublicAggregateMacro(vtkPointSet, DataSet)
Dataset for which search structure is build.
static void GetPoint(Point &point, vtkPointSet *dataset, const Array< int > *sample, int index)
Definition: PointLocator.h:701
FeatureInfo(const char *name, double weight=1.0, double slope=1.0, double intercept=.0)
Constructor.
Definition: PointLocator.h:93
double _z
z coordinate of Point
Definition: Point.h:48
FeatureInfo(int index=-2, double weight=1.0, double slope=1.0, double intercept=.0)
Constructor.
Definition: PointLocator.h:87
double _y
y coordinate of Point
Definition: Point.h:47
static PointLocator * New(vtkPointSet *dataset, const Array< int > *sample=NULL, const FeatureList *feature=NULL)
int NumberOfPoints(vtkDataSet *)
Number of points.
Array< int > FindClosestNPoints(int k, double *point, Array< double > *dist2=NULL)
double _Intercept
Rescaling intercept of feature/point data.
Definition: PointLocator.h:84
vtkSmartPointer< vtkOctreePointLocator > _VtkLocator
VTK point locator used for three-dimensional feature spaces.
Definition: PointLocator.h:208
string _Name
Name of feature/point data array.
Definition: PointLocator.h:80