Mantid
Loading...
Searching...
No Matches
NearestNeighbours.h
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2016 ISIS Rutherford Appleton Laboratory UKRI,
4// NScD Oak Ridge National Laboratory, European Spallation Source,
5// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6// SPDX - License - Identifier: GPL - 3.0 +
7#pragma once
8
9#include "MantidKernel/ANN/ANN.h"
10#include "MantidKernel/DllConfig.h"
11
12#include <Eigen/Core>
13#include <memory>
14#include <vector>
15
30namespace Mantid {
31namespace Kernel {
32
33//------------------------------------------------------------------------------
34// Helper classes
35//------------------------------------------------------------------------------
36
42public:
48 NNDataPoints(const int nPts, const int nElems) : m_nPts(nPts) { m_data = annAllocPts(m_nPts, nElems); }
49
50 ~NNDataPoints() { annDeallocPts(m_data); }
51
56 ANNpointArray rawData() { return m_data; }
57
66 ANNcoord *mutablePoint(const int i) {
67 if (i < m_nPts)
68 return m_data[i];
69 else
70 return nullptr;
71 }
72
73private:
75 const int m_nPts;
77 ANNpointArray m_data;
78};
79
80//------------------------------------------------------------------------------
81// NearestNeighbours implementation
82//------------------------------------------------------------------------------
83
84template <int N = 3> class DLLExport NearestNeighbours {
85
86public:
87 // typedefs for code brevity
88 using VectorType = Eigen::Matrix<double, N, 1>;
89 using NearestNeighbourResults = std::vector<std::tuple<VectorType, size_t, double>>;
90
95 NearestNeighbours(const std::vector<VectorType> &points) {
96 const auto numPoints = static_cast<int>(points.size());
97 if (numPoints == 0)
98 std::runtime_error("Need at least one point to initialise NearestNeighbours.");
99
100 m_dataPoints = std::make_unique<NNDataPoints>(numPoints, static_cast<int>(N));
101
102 for (size_t i = 0; i < points.size(); ++i) {
103 Eigen::Map<VectorType>(m_dataPoints->mutablePoint(static_cast<int>(i)), N, 1) = points[i];
104 }
105 m_kdTree = std::make_unique<ANNkd_tree>(m_dataPoints->rawData(), numPoints, static_cast<int>(N));
106 }
107
108 ~NearestNeighbours() { annClose(); }
109
111
122 NearestNeighbourResults findNearest(const VectorType &pos, const size_t k = 1, const double error = 0.0) {
123 const auto numNeighbours = static_cast<int>(k);
124 // create arrays to store the indices & distances of nearest neighbours
125 auto nnIndexList = std::unique_ptr<ANNidx[]>(new ANNidx[numNeighbours]);
126 auto nnDistList = std::unique_ptr<ANNdist[]>(new ANNdist[numNeighbours]);
127
128 // create ANNpoint from Eigen array
129 auto point = std::unique_ptr<ANNcoord[]>(annAllocPt(N));
130 Eigen::Map<VectorType>(point.get(), N, 1) = pos;
131
132 // find the k nearest neighbours
133 m_kdTree->annkSearch(point.get(), numNeighbours, nnIndexList.get(), nnDistList.get(), error);
134
135 return makeResults(k, std::move(nnIndexList), std::move(nnDistList));
136 }
137
138private:
148 NearestNeighbourResults makeResults(const size_t k, const std::unique_ptr<ANNidx[]> nnIndexList,
149 const std::unique_ptr<ANNdist[]> nnDistList) {
151 results.reserve(k);
152
153 for (size_t i = 0; i < k; ++i) {
154 // create Eigen array from ANNpoint
155 auto pos = m_dataPoints->mutablePoint(nnIndexList[i]);
156 VectorType point = Eigen::Map<VectorType>(pos, N, 1);
157 results.emplace_back(point, nnIndexList[i], nnDistList[i]);
158 }
159
160 return results;
161 }
162
164 std::unique_ptr<NNDataPoints> m_dataPoints;
166 std::unique_ptr<ANNkd_tree> m_kdTree;
167};
168} // namespace Kernel
169} // namespace Mantid
double error
Definition: IndexPeaks.cpp:133
#define DLLExport
Definitions of the DLLImport compiler directives for MSVC.
Definition: System.h:53
NNDataPoints is a thin RAII wrapper class around the ANNpointArray type.
ANNcoord * mutablePoint(const int i)
Access a raw point in the collection of points.
const int m_nPts
Number of points stored.
NNDataPoints(const int nPts, const int nElems)
Construct a new set of data points.
ANNpointArray m_data
Array of points for use with NN search.
ANNpointArray rawData()
Return a handle to the raw ANNpointArray wrapped by this class.
Eigen::Matrix< double, N, 1 > VectorType
std::unique_ptr< NNDataPoints > m_dataPoints
handle to the list of data points to search through
std::vector< std::tuple< VectorType, size_t, double > > NearestNeighbourResults
NearestNeighbours(const NearestNeighbours &)=delete
NearestNeighbours(const std::vector< VectorType > &points)
Create a nearest neighbour search object.
std::unique_ptr< ANNkd_tree > m_kdTree
handle to the ANN KD-tree used for searching
NearestNeighbourResults findNearest(const VectorType &pos, const size_t k=1, const double error=0.0)
Find the k nearest neighbours to a given point.
NearestNeighbourResults makeResults(const size_t k, const std::unique_ptr< ANNidx[]> nnIndexList, const std::unique_ptr< ANNdist[]> nnDistList)
Helper function to create a instance of NearestNeighbourResults.
Helper class which provides the Collimation Length for SANS instruments.