Warning, file /include/Geant4/G4Octree.icc was not indexed
or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029 #define OCTREE G4Octree<Iterator,Extractor,Point>
0030 #define OCTREE_TEMPLATE typename Iterator, class Extractor,typename Point
0031
0032
0033
0034 template <OCTREE_TEMPLATE>
0035 G4ThreadLocal G4Allocator<OCTREE>* OCTREE::fgAllocator = nullptr;
0036
0037
0038
0039 template <OCTREE_TEMPLATE>
0040 OCTREE::G4Octree()
0041 : functor_(Extractor())
0042 , head_(nullptr)
0043 , size_(0)
0044 {}
0045
0046
0047
0048 template <OCTREE_TEMPLATE>
0049 OCTREE::G4Octree(Iterator begin, Iterator end)
0050 : G4Octree(begin,end,Extractor())
0051 {
0052 head_ = nullptr;
0053 size_ = 0;
0054 }
0055
0056
0057
0058 template <OCTREE_TEMPLATE>
0059 OCTREE::G4Octree(Iterator begin, Iterator end, Extractor f)
0060 : functor_(f),head_(nullptr),size_(0)
0061 {
0062 std::vector<std::pair<Iterator,Point>> v;
0063 for(auto it=begin;it!=end;++it)
0064 {
0065 v.push_back(std::pair<Iterator,Point>(it,functor_(it)));
0066 }
0067 size_ = v.size();
0068 head_ = new Node(v);
0069 }
0070
0071
0072
0073 template <OCTREE_TEMPLATE>
0074 OCTREE::G4Octree(OCTREE::tree_type&& rhs)
0075 : functor_(rhs.functor_)
0076 , head_(rhs.head_)
0077 , size_(rhs.size_)
0078 {}
0079
0080
0081
0082 template <OCTREE_TEMPLATE>
0083 void OCTREE::swap(OCTREE::tree_type& rhs)
0084 {
0085 std::swap(head_, rhs.head_);
0086 std::swap(functor_, rhs.functor_);
0087 std::swap(size_, rhs.size_);
0088 }
0089
0090
0091
0092 template <OCTREE_TEMPLATE>
0093 typename OCTREE::tree_type& OCTREE::operator=(typename OCTREE::tree_type rhs)
0094 {
0095 swap(rhs);
0096 return *this;
0097 }
0098
0099
0100
0101 template <OCTREE_TEMPLATE>
0102 typename OCTREE::tree_type& OCTREE::operator=(typename OCTREE::tree_type&& rhs)
0103 {
0104 swap(rhs);
0105 return *this;
0106 }
0107
0108
0109 template <OCTREE_TEMPLATE>
0110 OCTREE::~G4Octree()
0111 {
0112 delete head_;
0113 }
0114
0115 template <OCTREE_TEMPLATE>
0116 size_t OCTREE::size() const
0117 {
0118 return size_;
0119 }
0120
0121 template <OCTREE_TEMPLATE>
0122 OCTREE::Node::Node(const NodeVector& input_values)
0123 : Node(input_values,
0124 G4DNABoundingBox(InnerIterator(input_values.begin()),
0125 InnerIterator(input_values.end())),
0126 0)
0127 {}
0128
0129
0130
0131 template <OCTREE_TEMPLATE>
0132 OCTREE::Node::Node(
0133 const NodeVector& input_values,
0134 const G4DNABoundingBox& box,
0135 size_t current_depth):
0136 fpValue(nullptr),
0137 fBigVolume(box),
0138 fNodeType(DEFAULT)
0139 {
0140 if (current_depth > max_depth)
0141 {
0142 init_max_depth_leaf(input_values);
0143 }
0144 else if (input_values.size() <= max_per_node)
0145 {
0146 init_leaf(input_values);
0147 }
0148 else
0149 {
0150 init_internal(input_values, current_depth);
0151 }
0152 }
0153
0154
0155 template <OCTREE_TEMPLATE>
0156 OCTREE::Node::~Node()
0157 {
0158 if (fNodeType == NodeTypes::INTERNAL)
0159 {
0160 childNodeArray& children = *static_cast<childNodeArray*>(fpValue);
0161 for (size_t i = 0; i < 8; ++i)
0162 {
0163 if (children[i] != nullptr)
0164 {
0165 delete children[i];
0166 children[i] = nullptr;
0167 }
0168 }
0169 delete &children;
0170 }
0171 else if (fNodeType == NodeTypes::LEAF)
0172 {
0173 auto toDelete = static_cast<LeafValues*>(fpValue);
0174 toDelete->size_ = 0;
0175 delete static_cast<LeafValues*>(fpValue);
0176 }
0177 else if (fNodeType == NodeTypes::MAX_DEPTH_LEAF)
0178 {
0179 delete static_cast<NodeVector*>(fpValue);
0180 }
0181 fpValue = nullptr;
0182 }
0183
0184
0185
0186 template <OCTREE_TEMPLATE>
0187 void OCTREE::Node::init_max_depth_leaf(
0188 const NodeVector& input_values)
0189 {
0190 fpValue = new NodeVector(input_values);
0191 fNodeType = NodeTypes::MAX_DEPTH_LEAF;
0192 }
0193
0194 template <OCTREE_TEMPLATE>
0195 void OCTREE::Node::init_leaf(const NodeVector& input_values)
0196 {
0197 std::array<std::pair<Iterator, Point>, max_per_node> a;
0198 std::copy(input_values.begin(), input_values.end(), a.begin());
0199 fpValue = new LeafValues{a, input_values.size()};
0200 fNodeType = NodeTypes::LEAF;
0201 }
0202
0203 template <OCTREE_TEMPLATE>
0204 void OCTREE::Node::init_internal(
0205 const NodeVector& input_values,
0206 size_t current_depth)
0207 {
0208 std::array<NodeVector, 8> childVectors;
0209 std::array<G4DNABoundingBox, 8> boxes = fBigVolume.partition();
0210 std::array<Node*, 8> children{};
0211 for (size_t child = 0; child < 8; ++child)
0212 {
0213 NodeVector& childVector = childVectors[child];
0214 childVector.reserve(input_values.size()/8);
0215 std::copy_if(input_values.begin(),input_values.end(),
0216 std::back_inserter(childVector),
0217 [&boxes, child](const std::pair<Iterator, Point>& element)
0218 -> G4bool
0219 {
0220 const Point& p = element.second;
0221 return boxes[child].contains(p);
0222 }
0223 );
0224 children[child] = childVector.empty()
0225 ? nullptr
0226 : new Node(childVector, boxes[child], ++current_depth);
0227 }
0228 fpValue = new std::array<Node*, 8>(children);
0229 fNodeType = NodeTypes::INTERNAL;
0230 }
0231
0232
0233 template <OCTREE_TEMPLATE>
0234 template <typename OutPutContainer>
0235 G4bool OCTREE::Node::radiusNeighbors(const Point& query,
0236 G4double radius,
0237 OutPutContainer& resultIndices) const
0238 {
0239 G4bool success = false;
0240 G4double distance = 0;
0241 if (fNodeType == NodeTypes::INTERNAL)
0242 {
0243 childNodeArray& children = *static_cast<childNodeArray*>(fpValue);
0244 for (auto eachChild : children)
0245 {
0246 if (eachChild == nullptr)
0247 {
0248 continue;
0249 }
0250 if(!eachChild->fBigVolume.overlap(query,radius))
0251 {
0252 continue;
0253 }
0254 success = eachChild->radiusNeighbors(query, radius, resultIndices) || success;
0255 }
0256 }
0257 else if (fNodeType == NodeTypes::LEAF)
0258 {
0259 if(fpValue != nullptr)
0260 {
0261 LeafValues& children = *static_cast<LeafValues*>(fpValue);
0262 for (size_t i = 0; i < children.size_; ++i)
0263 {
0264 distance = (query - std::get<1>(children.values_[i])).mag();
0265
0266 if(distance != 0)
0267 {
0268 if( distance < radius )
0269 {
0270 resultIndices.push_back(std::make_pair(std::get<0>(children.values_[i]),distance));
0271 success = true;
0272 }
0273 }
0274 }
0275 }
0276 }
0277 else if (fNodeType == NodeTypes::MAX_DEPTH_LEAF)
0278 {
0279 NodeVector& children = *static_cast<NodeVector*>(fpValue);
0280 for (auto & child : children)
0281 {
0282 const Point& point = std::get<1>(child);
0283
0284 distance = (query - point).mag();
0285 if( distance == 0. )
0286 {
0287 continue;
0288 }
0289 if( distance < radius )
0290 {
0291 if(distance == 0)
0292 {
0293 throw std::runtime_error("distance == 0 => OCTREE::Node::radiusNeighbors : find itself");
0294 }
0295 Iterator resultIndex = std::get<0>(child);
0296 resultIndices.push_back(std::make_pair(resultIndex,distance));
0297 success = true;
0298 }
0299 }
0300 }
0301 else
0302 {
0303 throw std::runtime_error("fNodeType is not set : find itself");
0304 }
0305 return success;
0306 }
0307
0308
0309
0310 template <OCTREE_TEMPLATE>
0311 template <typename OutPutContainer>
0312 void OCTREE::radiusNeighbors(const Point& query,
0313 const G4double& radius,
0314 OutPutContainer& resultIndices) const
0315 {
0316 resultIndices.clear();
0317 if (head_ == nullptr)
0318 {
0319 return;
0320 }
0321 head_->radiusNeighbors(query, radius, resultIndices);
0322 }
0323
0324
0325
0326 template <OCTREE_TEMPLATE>
0327 void* OCTREE::operator new(size_t)
0328 {
0329 if (!fgAllocator)
0330 {
0331 fgAllocator = new G4Allocator<OCTREE>;
0332 }
0333 return (void *) fgAllocator->MallocSingle();
0334 }
0335
0336 template <OCTREE_TEMPLATE>
0337 void OCTREE::operator delete(void *a)
0338 {
0339 fgAllocator->FreeSingle((OCTREE*)a);
0340 }