1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
|
/* This file is part of the OpenLB library
*
* Copyright (C) 2013 Thomas Henn, Mathias J. Krause
* E-mail contact: info@openlb.net
* The most recent release of OpenLB can be downloaded at
* <http://www.openlb.net/>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef NanoflannParticleAdaptor_H_
#define NanoflannParticleAdaptor_H_
#include "nanoflann.hpp"
using namespace std;
using namespace nanoflann;
namespace olb {
template<typename T, template<typename U> class PARTICLETYPE>
class ContactDetection;
template<typename T, template<typename U> class PARTICLETYPE>
class ParticleSystem3D;
template<typename coord_t, typename Derived>
class NanoflannParticleAdaptor {
public:
// typedef typename T coord_t;
const Derived &obj; //!< A const ref to the data set origin
/// The constructor that sets the data set source
NanoflannParticleAdaptor(const Derived &obj_)
: obj(obj_) {
}
/// CRTP helper method
inline const Derived& derived() const {
return obj;
}
// Must return the number of data points
inline size_t kdtree_get_point_count() const {
return derived().sizeInclShadow();
}
// Returns the distance between the vector "p1[0:size-1]" and the data point with index "idx_p2" stored in the class:
inline coord_t kdtree_distance(const coord_t *p1, const size_t idx_p2,
size_t size) const {
return std::pow(p1[0] - derived()[idx_p2].getPos()[0], 2) +
std::pow(p1[1] - derived()[idx_p2].getPos()[1], 2) +
std::pow(p1[2] - derived()[idx_p2].getPos()[2], 2);
// return (p1[0] - derived()[idx_p2].getPos()[0]) * (p1[0] - derived()[idx_p2].getPos()[0]) +
// (p1[1] - derived()[idx_p2].getPos()[1]) * (p1[1] - derived()[idx_p2].getPos()[1]) +
// (p1[2] - derived()[idx_p2].getPos()[2]) * (p1[2] - derived()[idx_p2].getPos()[2]);
}
// Returns the dim'th component of the idx'th point in the class:
// Since this is inlined and the "dim" argument is typically an immediate value, the
// "if/else's" are actually solved at compile time.
inline coord_t kdtree_get_pt(const size_t idx, int dim) const {
return derived()[idx].getPos()[dim];
}
// Optional bounding-box computation: return false to default to a standard bbox computation loop.
// Return true if the BBOX was already computed by the class and returned in "bb" so it can be avoided to redo it again.
// Look at bb.size() to find out the expected dimensionality (e.g. 2 or 3 for point clouds)
template<class BBOX>
bool kdtree_get_bbox(BBOX &bb) const {
return false;
}
};
template<typename T, template<typename U> class PARTICLETYPE>
class NanoflannContact : public ContactDetection<T, PARTICLETYPE> {
public:
NanoflannContact(ParticleSystem3D<T, PARTICLETYPE>& pSys, T sRad) : ContactDetection<T, PARTICLETYPE> (pSys, "Nanoflann"),
_pc2kd(pSys),
_index(3,_pc2kd, KDTreeSingleIndexAdaptorParams(10) ),
_sRad2(sRad*sRad),
_sRad(sRad)
{
_index.init();
_params.sorted = false;
}
virtual ContactDetection<T, PARTICLETYPE>* generate(ParticleSystem3D<T, PARTICLETYPE>& pSys) {
//std::cout << "calling NanoflannContact.generate()" << std::endl;
return new NanoflannContact(pSys,_sRad);
}
void sort() {
_index.buildIndex();
}
int getMatches(int pInt, std::vector<std::pair<size_t, T> >& matches) {
_index.radiusSearch(&this->_pSys[pInt].getPos()[0], _sRad2, matches, _params);
return matches.size();
}
private:
typedef NanoflannParticleAdaptor<T, ParticleSystem3D<T, PARTICLETYPE> > PC2KD;
const PC2KD _pc2kd;
typedef KDTreeSingleIndexAdaptor<L2_Simple_Adaptor<T, PC2KD > ,PC2KD, 3> kd_tree;
kd_tree _index;
nanoflann::SearchParams _params;
T _sRad2;
T _sRad;
};
} // namespace olb
#endif
|