File indexing completed on 2025-01-18 09:57:02
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef KDBVH_H_INCLUDED
0011 #define KDBVH_H_INCLUDED
0012
0013 namespace Eigen {
0014
0015 namespace internal {
0016
0017
0018 template<typename Scalar, int Dim>
0019 struct vector_int_pair
0020 {
0021 EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(Scalar, Dim)
0022 typedef Matrix<Scalar, Dim, 1> VectorType;
0023
0024 vector_int_pair(const VectorType &v, int i) : first(v), second(i) {}
0025
0026 VectorType first;
0027 int second;
0028 };
0029
0030
0031
0032 template<typename ObjectList, typename VolumeList, typename BoxIter>
0033 struct get_boxes_helper {
0034 void operator()(const ObjectList &objects, BoxIter boxBegin, BoxIter boxEnd, VolumeList &outBoxes)
0035 {
0036 outBoxes.insert(outBoxes.end(), boxBegin, boxEnd);
0037 eigen_assert(outBoxes.size() == objects.size());
0038 EIGEN_ONLY_USED_FOR_DEBUG(objects);
0039 }
0040 };
0041
0042 template<typename ObjectList, typename VolumeList>
0043 struct get_boxes_helper<ObjectList, VolumeList, int> {
0044 void operator()(const ObjectList &objects, int, int, VolumeList &outBoxes)
0045 {
0046 outBoxes.reserve(objects.size());
0047 for(int i = 0; i < (int)objects.size(); ++i)
0048 outBoxes.push_back(bounding_box(objects[i]));
0049 }
0050 };
0051
0052 }
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068 template<typename _Scalar, int _Dim, typename _Object> class KdBVH
0069 {
0070 public:
0071 enum { Dim = _Dim };
0072 typedef _Object Object;
0073 typedef std::vector<Object, aligned_allocator<Object> > ObjectList;
0074 typedef _Scalar Scalar;
0075 typedef AlignedBox<Scalar, Dim> Volume;
0076 typedef std::vector<Volume, aligned_allocator<Volume> > VolumeList;
0077 typedef int Index;
0078 typedef const int *VolumeIterator;
0079 typedef const Object *ObjectIterator;
0080
0081 KdBVH() {}
0082
0083
0084 template<typename Iter> KdBVH(Iter begin, Iter end) { init(begin, end, 0, 0); }
0085
0086
0087 template<typename OIter, typename BIter> KdBVH(OIter begin, OIter end, BIter boxBegin, BIter boxEnd) { init(begin, end, boxBegin, boxEnd); }
0088
0089
0090
0091 template<typename Iter> void init(Iter begin, Iter end) { init(begin, end, 0, 0); }
0092
0093
0094
0095 template<typename OIter, typename BIter> void init(OIter begin, OIter end, BIter boxBegin, BIter boxEnd)
0096 {
0097 objects.clear();
0098 boxes.clear();
0099 children.clear();
0100
0101 objects.insert(objects.end(), begin, end);
0102 int n = static_cast<int>(objects.size());
0103
0104 if(n < 2)
0105 return;
0106
0107 VolumeList objBoxes;
0108 VIPairList objCenters;
0109
0110
0111 internal::get_boxes_helper<ObjectList, VolumeList, BIter>()(objects, boxBegin, boxEnd, objBoxes);
0112
0113 objCenters.reserve(n);
0114 boxes.reserve(n - 1);
0115 children.reserve(2 * n - 2);
0116
0117 for(int i = 0; i < n; ++i)
0118 objCenters.push_back(VIPair(objBoxes[i].center(), i));
0119
0120 build(objCenters, 0, n, objBoxes, 0);
0121
0122 ObjectList tmp(n);
0123 tmp.swap(objects);
0124 for(int i = 0; i < n; ++i)
0125 objects[i] = tmp[objCenters[i].second];
0126 }
0127
0128
0129 inline Index getRootIndex() const { return (int)boxes.size() - 1; }
0130
0131
0132
0133 EIGEN_STRONG_INLINE void getChildren(Index index, VolumeIterator &outVBegin, VolumeIterator &outVEnd,
0134 ObjectIterator &outOBegin, ObjectIterator &outOEnd) const
0135 {
0136 if(index < 0) {
0137 outVBegin = outVEnd;
0138 if(!objects.empty())
0139 outOBegin = &(objects[0]);
0140 outOEnd = outOBegin + objects.size();
0141 return;
0142 }
0143
0144 int numBoxes = static_cast<int>(boxes.size());
0145
0146 int idx = index * 2;
0147 if(children[idx + 1] < numBoxes) {
0148 outVBegin = &(children[idx]);
0149 outVEnd = outVBegin + 2;
0150 outOBegin = outOEnd;
0151 }
0152 else if(children[idx] >= numBoxes) {
0153 outVBegin = outVEnd;
0154 outOBegin = &(objects[children[idx] - numBoxes]);
0155 outOEnd = outOBegin + 2;
0156 } else {
0157 outVBegin = &(children[idx]);
0158 outVEnd = outVBegin + 1;
0159 outOBegin = &(objects[children[idx + 1] - numBoxes]);
0160 outOEnd = outOBegin + 1;
0161 }
0162 }
0163
0164
0165 inline const Volume &getVolume(Index index) const
0166 {
0167 return boxes[index];
0168 }
0169
0170 private:
0171 typedef internal::vector_int_pair<Scalar, Dim> VIPair;
0172 typedef std::vector<VIPair, aligned_allocator<VIPair> > VIPairList;
0173 typedef Matrix<Scalar, Dim, 1> VectorType;
0174 struct VectorComparator
0175 {
0176 VectorComparator(int inDim) : dim(inDim) {}
0177 inline bool operator()(const VIPair &v1, const VIPair &v2) const { return v1.first[dim] < v2.first[dim]; }
0178 int dim;
0179 };
0180
0181
0182
0183
0184 void build(VIPairList &objCenters, int from, int to, const VolumeList &objBoxes, int dim)
0185 {
0186 eigen_assert(to - from > 1);
0187 if(to - from == 2) {
0188 boxes.push_back(objBoxes[objCenters[from].second].merged(objBoxes[objCenters[from + 1].second]));
0189 children.push_back(from + (int)objects.size() - 1);
0190 children.push_back(from + (int)objects.size());
0191 }
0192 else if(to - from == 3) {
0193 int mid = from + 2;
0194 std::nth_element(objCenters.begin() + from, objCenters.begin() + mid,
0195 objCenters.begin() + to, VectorComparator(dim));
0196 build(objCenters, from, mid, objBoxes, (dim + 1) % Dim);
0197 int idx1 = (int)boxes.size() - 1;
0198 boxes.push_back(boxes[idx1].merged(objBoxes[objCenters[mid].second]));
0199 children.push_back(idx1);
0200 children.push_back(mid + (int)objects.size() - 1);
0201 }
0202 else {
0203 int mid = from + (to - from) / 2;
0204 nth_element(objCenters.begin() + from, objCenters.begin() + mid,
0205 objCenters.begin() + to, VectorComparator(dim));
0206 build(objCenters, from, mid, objBoxes, (dim + 1) % Dim);
0207 int idx1 = (int)boxes.size() - 1;
0208 build(objCenters, mid, to, objBoxes, (dim + 1) % Dim);
0209 int idx2 = (int)boxes.size() - 1;
0210 boxes.push_back(boxes[idx1].merged(boxes[idx2]));
0211 children.push_back(idx1);
0212 children.push_back(idx2);
0213 }
0214 }
0215
0216 std::vector<int> children;
0217 VolumeList boxes;
0218 ObjectList objects;
0219 };
0220
0221 }
0222
0223 #endif