Warning, file /geant4/examples/advanced/dna/moleculardna/src/OctreeNode.cc 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 #include "OctreeNode.hh"
0028
0029 #include "G4VPhysicalVolume.hh"
0030
0031 #include <cassert>
0032 #include <utility>
0033
0034
0035
0036 OctreeNode::OctreeNode(const G4ThreeVector& position, const G4ThreeVector& halfLengths,
0037 G4int maxContents, OctreeNode* parent)
0038 : fPosition(position),
0039 fHalfLengths(halfLengths),
0040 fMaxContents(maxContents),
0041 fParent(parent),
0042 fChildren(std::array<OctreeNode*, 8>())
0043 {
0044 fHalfLengthsMag = fHalfLengths.mag();
0045 }
0046
0047 OctreeNode::~OctreeNode()
0048 {
0049
0050 for (auto& it : fChildren) {
0051 delete it;
0052 }
0053 }
0054
0055
0056
0057 const OctreeNode* OctreeNode::GetChildFromPosition(const G4ThreeVector& pos) const
0058 {
0059 G4ThreeVector localPosition = pos - fPosition;
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069 int bit2 = (localPosition.getX() < 0) ? 4 : 0;
0070 int bit1 = (localPosition.getY() < 0) ? 2 : 0;
0071 int bit0 = (localPosition.getZ() < 0) ? 1 : 0;
0072 return fChildren[bit0 + bit1 + bit2];
0073 }
0074
0075
0076
0077
0078 OctreeNode* OctreeNode::GetChildFromPosition(const G4ThreeVector& pos)
0079 {
0080 G4ThreeVector localPosition = pos - fPosition;
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090 int bit2 = (localPosition.getX() < 0) ? 4 : 0;
0091 int bit1 = (localPosition.getY() < 0) ? 2 : 0;
0092 int bit0 = (localPosition.getZ() < 0) ? 1 : 0;
0093 int idx = bit0 + bit1 + bit2;
0094
0095 assert(idx < (int)fChildren.size());
0096 return fChildren[idx];
0097 }
0098
0099
0100
0101 void OctreeNode::AddPhysicalVolume(G4VPhysicalVolume* pv)
0102 {
0103
0104 if (this->HasChildren()) {
0105 OctreeNode* child = this->GetChildFromPosition(pv->GetTranslation());
0106 child->AddPhysicalVolume(pv);
0107 }
0108 else {
0109
0110
0111 if ((G4int)fContents.size() == fMaxContents) {
0112 this->Split();
0113 this->AddPhysicalVolume(pv);
0114 }
0115 else {
0116 fContents.push_back(pv);
0117 }
0118 }
0119 }
0120
0121
0122
0123 void OctreeNode::Split()
0124 {
0125 G4ThreeVector hl = 0.5 * fHalfLengths;
0126 G4double xp = fPosition.getX();
0127 G4double yp = fPosition.getY();
0128 G4double zp = fPosition.getZ();
0129 G4double xl = hl.getX();
0130 G4double yl = hl.getY();
0131 G4double zl = hl.getZ();
0132 G4ThreeVector newpos;
0133
0134
0135 newpos = G4ThreeVector(xp + xl, yp + yl, zp + zl);
0136 fChildren[0] = new OctreeNode(newpos, hl, fMaxContents, this);
0137 newpos = G4ThreeVector(xp + xl, yp + yl, zp - zl);
0138 fChildren[1] = new OctreeNode(newpos, hl, fMaxContents, this);
0139 newpos = G4ThreeVector(xp + xl, yp - yl, zp + zl);
0140 fChildren[2] = new OctreeNode(newpos, hl, fMaxContents, this);
0141 newpos = G4ThreeVector(xp + xl, yp - yl, zp - zl);
0142 fChildren[3] = new OctreeNode(newpos, hl, fMaxContents, this);
0143 newpos = G4ThreeVector(xp - xl, yp + yl, zp + zl);
0144 fChildren[4] = new OctreeNode(newpos, hl, fMaxContents, this);
0145 newpos = G4ThreeVector(xp - xl, yp + yl, zp - zl);
0146 fChildren[5] = new OctreeNode(newpos, hl, fMaxContents, this);
0147 newpos = G4ThreeVector(xp - xl, yp - yl, zp + zl);
0148 fChildren[6] = new OctreeNode(newpos, hl, fMaxContents, this);
0149 newpos = G4ThreeVector(xp - xl, yp - yl, zp - zl);
0150 fChildren[7] = new OctreeNode(newpos, hl, fMaxContents, this);
0151
0152
0153
0154 for (int i = fContents.size() - 1; i >= 0; --i) {
0155 G4VPhysicalVolume* pv = fContents[i];
0156 OctreeNode* child = this->GetChildFromPosition(pv->GetTranslation());
0157 assert(child != this);
0158 child->AddPhysicalVolume(pv);
0159 }
0160 fContents.clear();
0161 }
0162
0163
0164
0165 std::vector<G4VPhysicalVolume*> OctreeNode::GetContents() const
0166 {
0167 if (this->HasChildren())
0168 {
0169 std::vector<G4VPhysicalVolume*> vec;
0170 std::vector<G4VPhysicalVolume*> childCont;
0171 for (auto it = fChildren.begin(); it != fChildren.end(); ++it) {
0172 childCont = (*it)->GetContents();
0173 for (auto jt = childCont.begin(); jt != childCont.end(); ++jt) {
0174 vec.push_back(*jt);
0175 }
0176 }
0177 return vec;
0178 }
0179 else
0180 {
0181 return fContents;
0182 }
0183 }
0184
0185
0186
0187
0188 const std::vector<G4VPhysicalVolume*> OctreeNode::SearchOctree(const G4ThreeVector& pos,
0189 G4double _rad) const
0190 {
0191
0192
0193
0194
0195 std::vector<const OctreeNode*> nodes;
0196 std::vector<const OctreeNode*> candidates;
0197 nodes.reserve(512);
0198 candidates.reserve(512);
0199
0200 if (this->HasChildren()) {
0201 for (auto it = this->GetChildren().begin(); it != this->GetChildren().end(); it++) {
0202 candidates.push_back(*it);
0203 }
0204 }
0205 else {
0206 candidates.push_back(this);
0207 }
0208
0209 const OctreeNode* aNode;
0210 G4double d;
0211 while (!candidates.empty()) {
0212 aNode = candidates.back();
0213 candidates.pop_back();
0214 d = (aNode->GetPosition() - pos).mag() - aNode->GetHalfLengthsMag();
0215
0216 if (d < _rad) {
0217 if (aNode->HasChildren()) {
0218 for (auto it = aNode->GetChildren().begin(); it != aNode->GetChildren().end(); ++it) {
0219 candidates.push_back(*it);
0220 }
0221 }
0222 else {
0223 nodes.push_back(aNode);
0224 }
0225 }
0226 }
0227
0228
0229
0230
0231 G4double r2 = _rad * _rad;
0232 std::vector<G4VPhysicalVolume*> pvols;
0233 for (auto it = nodes.begin(); it != nodes.end(); ++it) {
0234 std::vector<G4VPhysicalVolume*> conts = (*it)->GetContents();
0235 for (auto jt = conts.begin(); jt != conts.end(); ++jt) {
0236 if ((pos - (*jt)->GetTranslation()).mag2() < r2) {
0237 pvols.push_back((*jt));
0238 }
0239 }
0240 }
0241
0242 return pvols;
0243 }
0244
0245
0246
0247
0248 void OctreeNode::SearchOctree(const G4ThreeVector& pos, std::vector<G4VPhysicalVolume*>& out,
0249 G4double _rad) const
0250 {
0251
0252
0253
0254
0255 std::vector<const OctreeNode*> nodes;
0256 std::vector<const OctreeNode*> candidates;
0257 nodes.reserve(512);
0258 candidates.reserve(512);
0259
0260 if (this->HasChildren()) {
0261 for (auto it = this->GetChildren().begin(); it != this->GetChildren().end(); ++it) {
0262 candidates.push_back(*it);
0263 }
0264 }
0265 else {
0266 candidates.push_back(this);
0267 }
0268
0269 const OctreeNode* aNode;
0270 G4double d;
0271 while (!candidates.empty()) {
0272 aNode = candidates.back();
0273 candidates.pop_back();
0274 d = (aNode->GetPosition() - pos).mag() - aNode->GetHalfLengthsMag();
0275
0276 if (d < _rad) {
0277 if (aNode->HasChildren()) {
0278 for (auto it = aNode->GetChildren().begin(); it != aNode->GetChildren().end(); it++) {
0279 candidates.push_back(*it);
0280 }
0281 }
0282 else {
0283 nodes.push_back(aNode);
0284 }
0285 }
0286 }
0287
0288
0289 G4double r2 = _rad * _rad;
0290 for (auto it = nodes.begin(); it != nodes.end(); ++it) {
0291 std::vector<G4VPhysicalVolume*> conts = (*it)->GetContents();
0292 for (auto jt = conts.begin(); jt != conts.end(); ++jt) {
0293 if ((pos - (*jt)->GetTranslation()).mag2() < r2) {
0294 out.push_back((*jt));
0295 }
0296 }
0297 }
0298 }
0299
0300
0301
0302 const std::vector<G4VPhysicalVolume*> OctreeNode::SearchOctree(const G4ThreeVector& pos) const
0303 {
0304 const OctreeNode* child = GetChildFromPosition(pos);
0305 return child->GetContents();
0306 }
0307
0308
0309
0310 G4int OctreeNode::GetNumberOfTerminalNodes()
0311 {
0312 if (!this->HasChildren()) {
0313 return 1;
0314 }
0315
0316 G4int n = 0;
0317 for (auto it = this->GetChildren().begin(); it != this->GetChildren().end(); ++it) {
0318 n = n + (*it)->GetNumberOfTerminalNodes();
0319 }
0320
0321 return n;
0322 }
0323