File indexing completed on 2025-01-30 10:26:16
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef VOLUME_UTILITIES_H_
0009 #define VOLUME_UTILITIES_H_
0010
0011 #include "VecGeom/base/Vector3D.h"
0012 #include "VecGeom/base/Global.h"
0013 #include "VecGeom/base/RNG.h"
0014 #include "VecGeom/volumes/PlacedBox.h"
0015 #include "VecGeom/volumes/LogicalVolume.h"
0016 #include "VecGeom/navigation/NavigationState.h"
0017 #include "VecGeom/navigation/VNavigator.h"
0018 #include "VecGeom/navigation/GlobalLocator.h"
0019 #include "VecGeom/management/GeoManager.h"
0020
0021 #include "VecGeom/management/GeoManager.h"
0022
0023 #include <cstdio>
0024 #include <random>
0025 #include <vector>
0026 #include <random>
0027
0028 namespace vecgeom {
0029 inline namespace VECGEOM_IMPL_NAMESPACE {
0030 namespace volumeUtilities {
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041 VECGEOM_FORCE_INLINE
0042 bool IsHittingVolume(Vector3D<Precision> const &point, Vector3D<Precision> const &dir, VPlacedVolume const &volume)
0043 {
0044 assert(!volume.Contains(point));
0045 return volume.DistanceToIn(point, dir, vecgeom::kInfLength) < vecgeom::kInfLength;
0046 }
0047
0048
0049 inline bool IsHittingAnyDaughter(Vector3D<Precision> const &point, Vector3D<Precision> const &dir,
0050 LogicalVolume const &volume)
0051 {
0052 for (size_t daughter = 0; daughter < volume.GetDaughters().size(); ++daughter) {
0053 if (IsHittingVolume(point, dir, *volume.GetDaughters()[daughter])) {
0054 return true;
0055 }
0056 }
0057 return false;
0058 }
0059
0060
0061
0062
0063
0064
0065
0066
0067 VECGEOM_FORCE_INLINE
0068 Vector3D<Precision> SamplePoint(Vector3D<Precision> const &size, const Precision scale = 1)
0069 {
0070 const Vector3D<Precision> ret(scale * (1. - 2. * RNG::Instance().uniform()) * size[0],
0071 scale * (1. - 2. * RNG::Instance().uniform()) * size[1],
0072 scale * (1. - 2. * RNG::Instance().uniform()) * size[2]);
0073 return ret;
0074 }
0075
0076
0077
0078
0079
0080
0081
0082
0083 template <typename RngEngine>
0084 VECGEOM_FORCE_INLINE
0085 Vector3D<Precision> SamplePoint(Vector3D<Precision> const &size, RngEngine &rngengine, const Precision scale = 1)
0086 {
0087 std::uniform_real_distribution<double> dist(0, 2.);
0088 const Vector3D<Precision> ret(scale * (1. - dist(rngengine)) * size[0], scale * (1. - dist(rngengine)) * size[1],
0089 scale * (1. - dist(rngengine)) * size[2]);
0090 return ret;
0091 }
0092
0093
0094
0095
0096
0097
0098 VECGEOM_FORCE_INLINE
0099 Vector3D<Precision> SampleDirection()
0100 {
0101
0102 Vector3D<Precision> dir((1. - 2. * RNG::Instance().uniform()), (1. - 2. * RNG::Instance().uniform()),
0103 (1. - 2. * RNG::Instance().uniform()));
0104
0105 const Precision inverse_norm = 1. / std::sqrt(dir[0] * dir[0] + dir[1] * dir[1] + dir[2] * dir[2]);
0106 dir *= inverse_norm;
0107
0108 return dir;
0109 }
0110
0111
0112
0113
0114
0115 template <typename TrackContainer>
0116 VECGEOM_FORCE_INLINE
0117 void FillRandomDirections(TrackContainer &dirs)
0118 {
0119 dirs.resize(dirs.capacity());
0120 for (int i = 0, iMax = dirs.capacity(); i < iMax; ++i) {
0121 dirs.set(i, SampleDirection());
0122 }
0123 }
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139 template <typename TrackContainer>
0140 VECGEOM_FORCE_INLINE
0141 void FillBiasedDirections(VPlacedVolume const &volume, TrackContainer const &points, Precision bias,
0142 TrackContainer &dirs)
0143 {
0144 assert(bias >= 0. && bias <= 1.);
0145
0146 if (bias > 0. && volume.GetDaughters().size() == 0) {
0147 printf("\nFillBiasedDirections ERROR:\n bias=%f requested, but no daughter volumes found.\n", bias);
0148
0149
0150
0151
0152 bias = 0.0;
0153 }
0154
0155 const int size = dirs.capacity();
0156 int n_hits = 0;
0157 std::vector<bool> hit(size, false);
0158
0159
0160 FillRandomDirections(dirs);
0161
0162
0163 for (int track = 0; track < size; ++track) {
0164 if (IsHittingAnyDaughter(points[track], dirs[track], *volume.GetLogicalVolume())) {
0165 n_hits++;
0166 hit[track] = true;
0167 }
0168 }
0169
0170
0171 printf("VolumeUtilities: FillBiasedDirs: nhits/size = %i/%i and requested bias=%f\n", n_hits, size, bias);
0172 int tries = 0;
0173 int maxtries = 10000 * size;
0174 while (static_cast<Precision>(n_hits) / static_cast<Precision>(size) > bias) {
0175
0176 tries++;
0177 if (tries % 1000000 == 0) {
0178 printf("%s line %i: Warning: %i tries to reduce bias... volume=%s. Please check.\n", __FILE__, __LINE__, tries,
0179 volume.GetLabel().c_str());
0180 }
0181
0182 int track = static_cast<int>(static_cast<Precision>(size) * RNG::Instance().uniform());
0183 int internaltries = 0;
0184 while (hit[track]) {
0185 if (internaltries % 2) {
0186 dirs.set(track, SampleDirection());
0187 } else {
0188
0189 dirs.set(track, -dirs[track]);
0190 }
0191 internaltries++;
0192 if (!IsHittingAnyDaughter(points[track], dirs[track], *volume.GetLogicalVolume())) {
0193 n_hits--;
0194 hit[track] = false;
0195
0196 }
0197 if (internaltries % 100 == 0) {
0198
0199
0200
0201
0202 break;
0203 }
0204 }
0205 }
0206
0207
0208 {
0209 int crosscheckhits = 0;
0210 for (int track = 0; track < size; ++track)
0211 if (IsHittingAnyDaughter(points[track], dirs[track], *volume.GetLogicalVolume())) crosscheckhits++;
0212 assert(crosscheckhits == n_hits && "problem with hit count == 0");
0213 (void)crosscheckhits;
0214 }
0215
0216
0217 tries = 0;
0218 while (static_cast<Precision>(n_hits) / static_cast<Precision>(size) < bias && tries < maxtries) {
0219 int track = static_cast<int>(static_cast<Precision>(size) * RNG::Instance().uniform());
0220 while (!hit[track] && tries < maxtries) {
0221 ++tries;
0222 if (tries % 1000000 == 0) {
0223 printf("%s line %i: Warning: %i tries to increase bias... volume=%s, current bias=%i/%i=%f. Please check.\n",
0224 __FILE__, __LINE__, tries, volume.GetLabel().c_str(), n_hits, size,
0225 static_cast<Precision>(n_hits) / static_cast<Precision>(size));
0226 }
0227
0228
0229
0230
0231
0232 uint selecteddaughter = (uint)RNG::Instance().uniform() * volume.GetDaughters().size();
0233 VPlacedVolume const *daughter = volume.GetDaughters()[selecteddaughter];
0234 Vector3D<Precision> pointonsurface = daughter->GetUnplacedVolume()->SamplePointOnSurface();
0235
0236 Vector3D<Precision> dirtosurfacepoint =
0237 daughter->GetTransformation()->InverseTransform(pointonsurface) - points[track];
0238 dirtosurfacepoint.Normalize();
0239 dirs.set(track, dirtosurfacepoint);
0240
0241
0242
0243 if (IsHittingAnyDaughter(points[track], dirs[track], *volume.GetLogicalVolume())) {
0244 n_hits++;
0245 hit[track] = true;
0246 tries = 0;
0247 }
0248 }
0249 }
0250
0251
0252 {
0253 int crosscheckhits = 0;
0254 for (int p = 0; p < size; ++p)
0255 if (IsHittingAnyDaughter(points[p], dirs[p], *volume.GetLogicalVolume())) crosscheckhits++;
0256 assert(crosscheckhits == n_hits && "problem with hit count");
0257 (void)crosscheckhits;
0258 }
0259
0260 if (tries == maxtries) {
0261 printf("WARNING: NUMBER OF DIRECTORY SAMPLING TRIES EXCEEDED MAXIMUM; N_HITS %d; ACHIEVED BIAS %lf \n", n_hits,
0262 n_hits / (1. * size));
0263 }
0264 }
0265
0266
0267
0268
0269
0270 template <typename TrackContainer>
0271 VECGEOM_FORCE_INLINE
0272 void FillBiasedDirections(LogicalVolume const &volume, TrackContainer const &points, const Precision bias,
0273 TrackContainer &dirs)
0274 {
0275 VPlacedVolume const *const placed = volume.Place();
0276 FillBiasedDirections(*placed, points, bias, dirs);
0277 delete placed;
0278 }
0279
0280 VECGEOM_FORCE_INLINE
0281 Precision UncontainedCapacity(VPlacedVolume const &volume)
0282 {
0283 Precision momCapacity = const_cast<VPlacedVolume &>(volume).Capacity();
0284 Precision dauCapacity = 0.;
0285 unsigned int kk = 0;
0286 for (Vector<Daughter>::const_iterator j = volume.GetDaughters().cbegin(), jEnd = volume.GetDaughters().cend();
0287 j != jEnd; ++j, ++kk) {
0288 dauCapacity += const_cast<VPlacedVolume *>(*j)->Capacity();
0289 }
0290 return momCapacity - dauCapacity;
0291 }
0292
0293
0294
0295
0296
0297
0298
0299
0300
0301 template <typename TrackContainer>
0302 VECGEOM_FORCE_INLINE bool FillUncontainedPoints(VPlacedVolume const &volume, TrackContainer &points)
0303 {
0304 static double lastUncontCap = 0.0;
0305 double uncontainedCapacity = UncontainedCapacity(volume);
0306 if (uncontainedCapacity != lastUncontCap) {
0307 std::cout << "Uncontained capacity for " << volume.GetLabel() << ":" << uncontainedCapacity << " units\n";
0308 lastUncontCap = uncontainedCapacity;
0309 }
0310 if (uncontainedCapacity <= 1000 * kTolerance) {
0311 std::cout << "\nVolUtil: FillUncontPts: WARNING: Volume provided <" << volume.GetLabel()
0312 << "> does not have uncontained capacity! Method returns false.\n";
0313 return false;
0314 }
0315
0316 const int size = points.capacity();
0317 points.resize(points.capacity());
0318
0319 Vector3D<Precision> lower, upper, offset;
0320 volume.GetUnplacedVolume()->Extent(lower, upper);
0321 offset = 0.5 * (upper + lower);
0322 const Vector3D<Precision> dim = 0.5 * (upper - lower);
0323
0324 int totaltries = 0;
0325 for (int i = 0; i < size; ++i) {
0326 bool contained;
0327 Vector3D<Precision> point;
0328 totaltries = 0;
0329 do {
0330
0331 do {
0332 ++totaltries;
0333 if (totaltries % 10000 == 0) {
0334 printf("%s line %i: Warning: %i tries to find uncontained points... volume=%s. Please check.\n", __FILE__,
0335 __LINE__, totaltries, volume.GetLabel().c_str());
0336 }
0337 if (totaltries % 5000000 == 0) {
0338 double ratio = 1.0 * i / totaltries;
0339 printf("Progress : %i tries ( succeeded = %i , ratio %f %% ) to find uncontained points... volume=%s.\n",
0340 totaltries, i, 100. * ratio, volume.GetLabel().c_str());
0341 }
0342
0343 point = offset + SamplePoint(dim);
0344 } while (!volume.UnplacedContains(point));
0345 points.set(i, point);
0346
0347 contained = false;
0348 int kk = 0;
0349 for (Vector<Daughter>::const_iterator j = volume.GetDaughters().cbegin(), jEnd = volume.GetDaughters().cend();
0350 j != jEnd; ++j, ++kk) {
0351 if ((*j)->Contains(points[i])) {
0352 contained = true;
0353 break;
0354 }
0355 }
0356 } while (contained);
0357 }
0358 return true;
0359 }
0360
0361 template <typename TrackContainer>
0362 VECGEOM_FORCE_INLINE bool FillUncontainedPoints(LogicalVolume const &volume, TrackContainer &points)
0363 {
0364 VPlacedVolume const *const placed = volume.Place();
0365 bool good = FillUncontainedPoints(*placed, points);
0366 delete placed;
0367
0368 return good;
0369 }
0370
0371
0372
0373
0374
0375
0376
0377
0378
0379
0380
0381
0382 template <typename RandomEngine, typename TrackContainer>
0383 VECGEOM_FORCE_INLINE bool FillUncontainedPoints(VPlacedVolume const &volume, RandomEngine &rngengine,
0384 TrackContainer &points)
0385 {
0386 static double lastUncontCap = 0.0;
0387 double uncontainedCapacity = UncontainedCapacity(volume);
0388 if (uncontainedCapacity != lastUncontCap) {
0389 printf("Uncontained capacity for %s: %g units\n", volume.GetLabel().c_str(), uncontainedCapacity);
0390 lastUncontCap = uncontainedCapacity;
0391 }
0392 double totalcapacity = const_cast<VPlacedVolume &>(volume).Capacity();
0393
0394 std::cout << "\nVolUtil: FillUncontPts: Volume <" << volume.GetLabel() << " capacities: total = " << totalcapacity
0395 << " uncontained = " << uncontainedCapacity << "\n";
0396
0397 if (uncontainedCapacity <= 1000 * kTolerance) {
0398
0399 std::cout << "\nVolUtil: FillUncontPts: ERROR: Volume provided <" << volume.GetLabel()
0400 << "> does not have uncontained capacity! "
0401 << " Value = " << uncontainedCapacity << " \n"
0402 << " contained = " << totalcapacity
0403
0404 ;
0405
0406 return false;
0407
0408 }
0409
0410 const int size = points.capacity();
0411 points.resize(points.capacity());
0412
0413 Vector3D<Precision> lower, upper, offset;
0414 volume.GetUnplacedVolume()->Extent(lower, upper);
0415 offset = 0.5 * (upper + lower);
0416 const Vector3D<Precision> dim = 0.5 * (upper - lower);
0417
0418 const int maxtries = 100 * 1000 * 1000;
0419
0420 int tries = 0;
0421 int i;
0422 for (i = 0; i < size; ++i) {
0423 bool contained;
0424 Vector3D<Precision> point;
0425 do {
0426
0427 int onego = 0;
0428 do {
0429 ++tries;
0430 onego++;
0431 if (onego % 100000 == 0) {
0432 printf("%s line %i: Warning: %i tries ( success = %i ) to find uncontained points... volume=%s. Please "
0433 "check.\n",
0434 __FILE__, __LINE__, tries, i, volume.GetLabel().c_str());
0435 }
0436 if (tries % 5000000 == 0) {
0437 double ratio = 1.0 * i / tries;
0438 printf("Progress : %i tries ( succeeded = %i , ratio %f %% ) to find uncontained points... volume=%s.\n",
0439 tries, i, 100.0 * ratio, volume.GetLabel().c_str());
0440 }
0441
0442 point = offset + SamplePoint(dim, rngengine);
0443 } while (!volume.UnplacedContains(point));
0444 points.set(i, point);
0445
0446 contained = false;
0447 int kk = 0;
0448 for (Vector<Daughter>::const_iterator j = volume.GetDaughters().cbegin(), jEnd = volume.GetDaughters().cend();
0449 j != jEnd; ++j, ++kk) {
0450 if ((*j)->Contains(points[i])) {
0451 contained = true;
0452 break;
0453 }
0454 }
0455 } while (contained && tries < maxtries);
0456
0457 if (tries >= maxtries) break;
0458 }
0459 std::cout << " FillUncontained: trials " << tries << " for num points = " << i << " ( out of " << size
0460 << " requested - " << " success ratio = " << (i * 1.0) / tries << "\n";
0461 return (i > 0);
0462 }
0463
0464 template <typename RandomEngine, typename TrackContainer>
0465 VECGEOM_FORCE_INLINE bool FillUncontainedPoints(LogicalVolume const &volume, RandomEngine &rngengine,
0466 TrackContainer &points)
0467 {
0468 VPlacedVolume const *const placed = volume.Place();
0469 bool good = FillUncontainedPoints(*placed, rngengine, points);
0470 delete placed;
0471
0472 return good;
0473 }
0474
0475
0476
0477
0478
0479
0480
0481
0482
0483
0484
0485 template <typename TrackContainer>
0486 VECGEOM_FORCE_INLINE
0487 bool FillRandomPoints(VPlacedVolume const &volume, TrackContainer &points)
0488 {
0489 const int size = points.capacity();
0490 points.resize(points.capacity());
0491
0492 int tries = 0;
0493
0494 Vector3D<Precision> lower, upper, offset;
0495 volume.GetUnplacedVolume()->Extent(lower, upper);
0496 offset = 0.5 * (upper + lower);
0497 const Vector3D<Precision> dim = 0.5 * (upper - lower);
0498
0499 for (int i = 0; i < size; ++i) {
0500 Vector3D<Precision> point;
0501 do {
0502 ++tries;
0503 if (tries % 1000000 == 0) {
0504 printf("%s line %i: Warning: %i tries to find contained points... volume=%s. Please check.\n", __FILE__,
0505 __LINE__, tries, volume.GetLabel().c_str());
0506 }
0507 if (tries > 100000000) {
0508 printf("%s line %i: giving up\n", __FILE__, __LINE__);
0509 return false;
0510 }
0511 point = offset + SamplePoint(dim);
0512 } while (!volume.UnplacedContains(point));
0513 points.set(i, point);
0514 }
0515 return true;
0516 }
0517
0518
0519
0520
0521
0522
0523
0524
0525
0526
0527
0528 template <typename TrackContainer>
0529 VECGEOM_FORCE_INLINE
0530 bool FillRandomPoints(VUnplacedVolume const &volume, TrackContainer &points)
0531 {
0532 const int size = points.capacity();
0533 points.resize(points.capacity());
0534
0535 int tries = 0;
0536
0537 Vector3D<Precision> lower, upper, offset;
0538 volume.Extent(lower, upper);
0539 offset = 0.5 * (upper + lower);
0540 const Vector3D<Precision> dim = 0.5 * (upper - lower);
0541
0542 for (int i = 0; i < size; ++i) {
0543 Vector3D<Precision> point;
0544 do {
0545 ++tries;
0546 if (tries % 1000000 == 0) {
0547 printf("%s line %i: Warning: %i tries to find contained points... in UnplacedVolume. Please check.\n", __FILE__,
0548 __LINE__, tries);
0549 }
0550 if (tries > 100000000) {
0551 printf("%s line %i: giving up\n", __FILE__, __LINE__);
0552 return false;
0553 }
0554 point = offset + SamplePoint(dim);
0555 } while (!volume.Contains(point));
0556 points.set(i, point);
0557 }
0558 return true;
0559 }
0560
0561
0562
0563
0564
0565
0566
0567
0568 template <typename TrackContainer>
0569 VECGEOM_FORCE_INLINE
0570 void FillContainedPoints(VPlacedVolume const &volume, const double bias, TrackContainer &points,
0571 const bool placed = true)
0572 {
0573
0574 const int size = points.capacity();
0575 points.resize(points.capacity());
0576
0577 Vector3D<Precision> lower, upper, offset;
0578 volume.Extent(lower, upper);
0579 offset = 0.5 * (upper + lower);
0580 const Vector3D<Precision> dim = 0.5 * (upper - lower);
0581
0582 int insideCount = 0;
0583 std::vector<bool> insideVector(size, false);
0584 for (int i = 0; i < size; ++i) {
0585 points.set(i, offset + SamplePoint(dim));
0586
0587 for (Vector<Daughter>::const_iterator v = volume.GetDaughters().cbegin(), v_end = volume.GetDaughters().cend();
0588 v != v_end; ++v) {
0589 bool inside = (placed) ? (*v)->Contains(points[i]) : (*v)->UnplacedContains(points[i]);
0590 if (inside) {
0591 ++insideCount;
0592 insideVector[i] = true;
0593 }
0594 }
0595 }
0596
0597
0598 int i = 0;
0599 int totaltries = 0;
0600 while (static_cast<double>(insideCount) / static_cast<double>(size) > bias) {
0601 while (!insideVector[i])
0602 ++i;
0603 bool contained;
0604 do {
0605 ++totaltries;
0606 if (totaltries % 1000000 == 0) {
0607 printf("%s line %i: Warning: %i totaltries to reduce bias... volume=%s. Please check.\n", __FILE__, __LINE__,
0608 totaltries, volume.GetLabel().c_str());
0609 }
0610
0611 points.set(i, offset + SamplePoint(dim));
0612 contained = false;
0613 for (Vector<Daughter>::const_iterator v = volume.GetDaughters().cbegin(), v_end = volume.GetDaughters().end();
0614 v != v_end; ++v) {
0615 bool inside = (placed) ? (*v)->Contains(points[i]) : (*v)->UnplacedContains(points[i]);
0616 if (inside) {
0617 contained = true;
0618 break;
0619 }
0620 }
0621 } while (contained);
0622 insideVector[i] = false;
0623
0624 --insideCount;
0625 ++i;
0626 }
0627
0628 int tries;
0629
0630 i = 0;
0631 tries = 0;
0632 SOA3D<Precision> daughterpoint(1);
0633 while (static_cast<double>(insideCount) / static_cast<double>(size) < bias) {
0634 while (insideVector[i])
0635 ++i;
0636 bool contained = false;
0637 do {
0638 ++tries;
0639 if (tries % 1000000 == 0) {
0640 printf("%s line %i: Warning: %i tries to increase bias... volume=%s. Please check.\n", __FILE__, __LINE__,
0641 tries, volume.GetLabel().c_str());
0642 }
0643
0644 auto ndaughters = volume.GetDaughters().size();
0645 if (ndaughters == 1) {
0646
0647 auto daughter = volume.GetDaughters().operator[](0);
0648 FillRandomPoints(*daughter, daughterpoint);
0649 points.set(i, placed ? volume.GetTransformation()->InverseTransform(daughterpoint[0]) : daughterpoint[0]);
0650 contained = true;
0651 } else {
0652 const Vector3D<Precision> sample = offset + SamplePoint(dim);
0653 for (Vector<Daughter>::const_iterator v = volume.GetDaughters().cbegin(), v_end = volume.GetDaughters().cend();
0654 v != v_end; ++v) {
0655 bool inside = (placed) ? (*v)->Contains(sample) : (*v)->UnplacedContains(sample);
0656 if (inside) {
0657 points.set(i, sample);
0658 contained = true;
0659 break;
0660 }
0661 }
0662 }
0663
0664 } while (!contained);
0665 insideVector[i] = true;
0666 tries = 0;
0667 ++insideCount;
0668 ++i;
0669 }
0670 }
0671
0672 template <typename TrackContainer>
0673 VECGEOM_FORCE_INLINE
0674 void FillContainedPoints(VPlacedVolume const &volume, TrackContainer &points, const bool placed = true)
0675 {
0676 FillContainedPoints<TrackContainer>(volume, 1, points, placed);
0677 }
0678
0679
0680
0681
0682
0683
0684
0685 template <typename TrackContainer>
0686 VECGEOM_FORCE_INLINE
0687 void FillRandomPoints(Vector3D<Precision> const &lowercorner, Vector3D<Precision> const &uppercorner,
0688 TrackContainer &points)
0689 {
0690 const int size = points.capacity();
0691 points.resize(points.capacity());
0692 Vector3D<Precision> dim = (uppercorner - lowercorner) / 2.;
0693 Vector3D<Precision> offset = (uppercorner + lowercorner) / 2.;
0694 for (int i = 0; i < size; ++i) {
0695 points.set(i, offset + SamplePoint(dim));
0696 }
0697 }
0698
0699
0700
0701
0702
0703
0704
0705
0706
0707 template <typename TrackContainer, typename ExcludedVol, bool exlu = true>
0708 VECGEOM_FORCE_INLINE
0709 void FillRandomPoints(Vector3D<Precision> const &lowercorner, Vector3D<Precision> const &uppercorner,
0710 ExcludedVol const &vol, TrackContainer &points)
0711 {
0712 const int size = points.capacity();
0713 points.resize(points.capacity());
0714 Vector3D<Precision> dim = (uppercorner - lowercorner) / 2.;
0715 Vector3D<Precision> offset = (uppercorner + lowercorner) / 2.;
0716 for (int i = 0; i < size; ++i) {
0717 Vector3D<Precision> p;
0718 do {
0719 p = offset + SamplePoint(dim);
0720 } while (!(exlu ^ vol.Contains(p)));
0721 points.set(i, p);
0722 }
0723 }
0724
0725
0726
0727
0728
0729
0730
0731 template <typename TrackContainer>
0732 VECGEOM_FORCE_INLINE
0733 void FillRandomPoints(Vector3D<Precision> const &dim, TrackContainer &points)
0734 {
0735 FillRandomPoints(Vector3D<Precision>(-dim.x(), -dim.y(), -dim.z()), Vector3D<Precision>(dim.x(), dim.y(), dim.z()),
0736 points);
0737 }
0738
0739
0740
0741
0742
0743
0744
0745
0746
0747
0748
0749
0750
0751
0752
0753
0754
0755 template <typename TrackContainer>
0756 inline void FillGlobalPointsAndDirectionsForLogicalVolume(LogicalVolume const *lvol, TrackContainer &localpoints,
0757 TrackContainer &globalpoints, TrackContainer &directions,
0758 Precision fraction, int np)
0759 {
0760
0761
0762
0763
0764 std::list<NavigationState *> allpaths;
0765 GeoManager::Instance().getAllPathForLogicalVolume(lvol, allpaths);
0766
0767 NavigationState *s1 = NavigationState::MakeInstance(GeoManager::Instance().getMaxDepth());
0768 NavigationState *s2 = NavigationState::MakeInstance(GeoManager::Instance().getMaxDepth());
0769 int virtuallyhitsdaughter = 0;
0770 int reallyhitsdaughter = 0;
0771 if (allpaths.size() > 0) {
0772
0773 VPlacedVolume const *pvol = allpaths.front()->Top();
0774
0775
0776 bool good = FillUncontainedPoints(*pvol, localpoints);
0777
0778 if (!good) {
0779 std::cerr << "FATAL ERROR> FillUncontainedPoints failed for volume " << pvol->GetName() << std::endl;
0780 exit(1);
0781 }
0782
0783
0784 FillBiasedDirections(*lvol, localpoints, fraction, directions);
0785
0786
0787 globalpoints.resize(globalpoints.capacity());
0788 int placedcount = 0;
0789
0790 while (placedcount < np) {
0791 std::list<NavigationState *>::iterator iter = allpaths.begin();
0792 while (placedcount < np && iter != allpaths.end()) {
0793
0794 Transformation3D m;
0795 (*iter)->TopMatrix(m);
0796
0797 bool hitsdaughter = IsHittingAnyDaughter(localpoints[placedcount], directions[placedcount], *lvol);
0798 if (hitsdaughter) virtuallyhitsdaughter++;
0799 globalpoints.set(placedcount, m.InverseTransform(localpoints[placedcount]));
0800 directions.set(placedcount, m.InverseTransformDirection(directions[placedcount]));
0801
0802
0803 s1->Clear();
0804 s2->Clear();
0805 GlobalLocator::LocateGlobalPoint(GeoManager::Instance().GetWorld(), globalpoints[placedcount], *s1, true);
0806 assert(s1->Top()->GetLogicalVolume() == lvol);
0807 Precision step = vecgeom::kInfLength;
0808 auto nav = s1->Top()->GetLogicalVolume()->GetNavigator();
0809 nav->FindNextBoundaryAndStep(globalpoints[placedcount], directions[placedcount], *s1, *s2, vecgeom::kInfLength,
0810 step);
0811 #ifdef DEBUG
0812 if (!hitsdaughter) assert(s1->Distance(*s2) > s2->GetCurrentLevel() - s1->GetCurrentLevel());
0813 #endif
0814 if (hitsdaughter)
0815 if (s1->Distance(*s2) == s2->GetCurrentLevel() - s1->GetCurrentLevel()) {
0816 reallyhitsdaughter++;
0817 }
0818
0819 placedcount++;
0820 iter++;
0821 }
0822 }
0823 } else {
0824
0825 printf("VolumeUtilities: FillGlobalPointsAndDirectionsForLogicalVolume()... ERROR condition detected.\n");
0826 }
0827 printf(" really hits %d, virtually hits %d ", reallyhitsdaughter, virtuallyhitsdaughter);
0828 NavigationState::ReleaseInstance(s1);
0829 NavigationState::ReleaseInstance(s2);
0830 std::list<NavigationState *>::iterator iter = allpaths.begin();
0831 while (iter != allpaths.end()) {
0832 NavigationState::ReleaseInstance(*iter);
0833 ++iter;
0834 }
0835 }
0836
0837
0838 template <typename TrackContainer>
0839 inline void FillGlobalPointsAndDirectionsForLogicalVolume(std::string const &name, TrackContainer &localpoints,
0840 TrackContainer &globalpoints, TrackContainer &directions,
0841 Precision fraction, int np)
0842 {
0843
0844 LogicalVolume const *vol = GeoManager::Instance().FindLogicalVolume(name.c_str());
0845 if (vol != NULL)
0846 FillGlobalPointsAndDirectionsForLogicalVolume(vol, localpoints, globalpoints, directions, fraction, np);
0847 }
0848
0849
0850 template <typename TrackContainer>
0851 inline void FillGlobalPointsAndDirectionsForLogicalVolume(int id, TrackContainer &localpoints,
0852 TrackContainer &globalpoints, TrackContainer &directions,
0853 Precision fraction, int np)
0854 {
0855
0856 LogicalVolume const *vol = GeoManager::Instance().FindLogicalVolume(id);
0857 if (vol != NULL)
0858 FillGlobalPointsAndDirectionsForLogicalVolume(vol, localpoints, globalpoints, directions, fraction, np);
0859 }
0860
0861
0862
0863
0864
0865
0866
0867
0868
0869
0870
0871
0872 template <typename TrackContainer>
0873 inline void FillGlobalPointsForLogicalVolume(LogicalVolume const *lvol, TrackContainer &localpoints,
0874 TrackContainer &globalpoints, int np, bool maybeindaughters = false)
0875 {
0876
0877
0878
0879
0880 std::list<NavigationState *> allpaths;
0881 GeoManager::Instance().getAllPathForLogicalVolume(lvol, allpaths);
0882
0883 if (allpaths.size() > 0) {
0884
0885 VPlacedVolume const *pvol = allpaths.front()->Top();
0886
0887 if (maybeindaughters) {
0888 FillContainedPoints(*pvol, localpoints);
0889 } else {
0890
0891 bool good = FillUncontainedPoints(*pvol, localpoints);
0892
0893 if (!good) {
0894 std::cerr << "FATAL ERROR> FillUncontainedPoints failed for volume " << pvol->GetName() << std::endl;
0895 exit(1);
0896 }
0897 }
0898
0899
0900 globalpoints.resize(globalpoints.capacity());
0901 int placedcount = 0;
0902
0903 while (placedcount < np) {
0904 std::list<NavigationState *>::iterator iter = allpaths.begin();
0905 while (placedcount < np && iter != allpaths.end()) {
0906
0907 Transformation3D m;
0908 (*iter)->TopMatrix(m);
0909
0910 globalpoints.set(placedcount, m.InverseTransform(localpoints[placedcount]));
0911
0912 placedcount++;
0913 iter++;
0914 }
0915 }
0916 } else {
0917
0918 printf("VolumeUtilities: FillGlobalPointsForLogicalVolume()... ERROR condition detected.\n");
0919 }
0920
0921 std::list<NavigationState *>::iterator iter = allpaths.begin();
0922 while (iter != allpaths.end()) {
0923 NavigationState::ReleaseInstance(*iter);
0924 ++iter;
0925 }
0926 }
0927
0928
0929 template <typename TrackContainer>
0930 inline void FillGlobalPointsForLogicalVolume(std::string const &name, TrackContainer &localpoints,
0931 TrackContainer &globalpoints, int np)
0932 {
0933
0934 LogicalVolume const *vol = GeoManager::Instance().FindLogicalVolume(name.c_str());
0935 if (vol != NULL) FillGlobalPointsForLogicalVolume(vol, localpoints, globalpoints, np);
0936 }
0937
0938
0939 template <typename TrackContainer>
0940 inline void FillGlobalPointsForLogicalVolume(int id, TrackContainer &localpoints, TrackContainer &globalpoints, int np)
0941 {
0942
0943 LogicalVolume const *vol = GeoManager::Instance().FindLogicalVolume(id);
0944 if (vol != NULL) FillGlobalPointsForLogicalVolume(vol, localpoints, globalpoints, np);
0945 }
0946
0947 inline Precision GetRadiusInRing(Precision rmin, Precision rmax)
0948 {
0949
0950
0951 if (rmin <= 0.) {
0952 return rmax * std::sqrt(RNG::Instance().uniform());
0953 }
0954 if (rmin != rmax) {
0955 Precision rmin2 = rmin * rmin;
0956 Precision rmax2 = rmax * rmax;
0957 return std::sqrt(rmin2 + RNG::Instance().uniform() * (rmax2 - rmin2));
0958 }
0959 return rmin;
0960 }
0961
0962
0963
0964
0965
0966
0967
0968
0969
0970
0971
0972
0973
0974
0975
0976
0977 VECGEOM_FORCE_INLINE
0978 bool IntersectionExist(Vector3D<Precision> const lowercornerFirstBox, Vector3D<Precision> const uppercornerFirstBox,
0979 Vector3D<Precision> const lowercornerSecondBox, Vector3D<Precision> const uppercornerSecondBox)
0980 {
0981
0982
0983
0984
0985
0986 if (uppercornerFirstBox.x() < lowercornerSecondBox.x()) return false;
0987
0988
0989 if (lowercornerFirstBox.x() > uppercornerSecondBox.x()) return false;
0990
0991
0992 if (uppercornerFirstBox.y() < lowercornerSecondBox.y()) return false;
0993
0994
0995 if (lowercornerFirstBox.y() > uppercornerSecondBox.y()) return false;
0996
0997
0998 if (uppercornerFirstBox.z() < lowercornerSecondBox.z()) return false;
0999
1000
1001 if (lowercornerFirstBox.z() > uppercornerSecondBox.z()) return false;
1002
1003 return true;
1004 }
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022 VECGEOM_FORCE_INLINE
1023 bool IntersectionExist(Vector3D<Precision> const lowercornerFirstBox, Vector3D<Precision> const uppercornerFirstBox,
1024 Vector3D<Precision> const lowercornerSecondBox, Vector3D<Precision> const uppercornerSecondBox,
1025 Transformation3D const *transformFirstBox, Transformation3D const *transformSecondBox, bool aux)
1026 {
1027
1028
1029 Precision halfAx, halfAy, halfAz;
1030 Precision halfBx, halfBy, halfBz;
1031
1032 halfAx = std::fabs(uppercornerFirstBox.x() - lowercornerFirstBox.x()) / 2.;
1033 halfAy = std::fabs(uppercornerFirstBox.y() - lowercornerFirstBox.y()) / 2.;
1034 halfAz = std::fabs(uppercornerFirstBox.z() - lowercornerFirstBox.z()) / 2.;
1035
1036 halfBx = std::fabs(uppercornerSecondBox.x() - lowercornerSecondBox.x()) / 2.;
1037 halfBy = std::fabs(uppercornerSecondBox.y() - lowercornerSecondBox.y()) / 2.;
1038 halfBz = std::fabs(uppercornerSecondBox.z() - lowercornerSecondBox.z()) / 2.;
1039
1040 Vector3D<Precision> pA = transformFirstBox->InverseTransform(Vector3D<Precision>(0, 0, 0));
1041 Vector3D<Precision> pB = transformSecondBox->InverseTransform(Vector3D<Precision>(0, 0, 0));
1042 Vector3D<Precision> T = pB - pA;
1043
1044 Vector3D<Precision> Ax = transformFirstBox->InverseTransformDirection(Vector3D<Precision>(1., 0., 0.));
1045 Vector3D<Precision> Ay = transformFirstBox->InverseTransformDirection(Vector3D<Precision>(0., 1., 0.));
1046 Vector3D<Precision> Az = transformFirstBox->InverseTransformDirection(Vector3D<Precision>(0., 0., 1.));
1047
1048 Vector3D<Precision> Bx = transformSecondBox->InverseTransformDirection(Vector3D<Precision>(1., 0., 0.));
1049 Vector3D<Precision> By = transformSecondBox->InverseTransformDirection(Vector3D<Precision>(0., 1., 0.));
1050 Vector3D<Precision> Bz = transformSecondBox->InverseTransformDirection(Vector3D<Precision>(0., 0., 1.));
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061 if (std::fabs(T.Dot(Ax)) >
1062 (halfAx + std::fabs(halfBx * Ax.Dot(Bx)) + std::fabs(halfBy * Ax.Dot(By)) + std::fabs(halfBz * Ax.Dot(Bz)))) {
1063 return false;
1064 }
1065
1066
1067
1068 if (std::fabs(T.Dot(Ay)) >
1069 (halfAy + std::fabs(halfBx * Ay.Dot(Bx)) + std::fabs(halfBy * Ay.Dot(By)) + std::fabs(halfBz * Ay.Dot(Bz)))) {
1070 return false;
1071 }
1072
1073
1074
1075 if (std::fabs(T.Dot(Az)) >
1076 (halfAz + std::fabs(halfBx * Az.Dot(Bx)) + std::fabs(halfBy * Az.Dot(By)) + std::fabs(halfBz * Az.Dot(Bz)))) {
1077 return false;
1078 }
1079
1080
1081
1082 if (std::fabs(T.Dot(Bx)) >
1083 (halfBx + std::fabs(halfAx * Ax.Dot(Bx)) + std::fabs(halfAy * Ay.Dot(Bx)) + std::fabs(halfAz * Az.Dot(Bx)))) {
1084 return false;
1085 }
1086
1087
1088
1089 if (std::fabs(T.Dot(By)) >
1090 (halfBy + std::fabs(halfAx * Ax.Dot(By)) + std::fabs(halfAy * Ay.Dot(By)) + std::fabs(halfAz * Az.Dot(By)))) {
1091 return false;
1092 }
1093
1094
1095
1096 if (std::fabs(T.Dot(Bz)) >
1097 (halfBz + std::fabs(halfAx * Ax.Dot(Bz)) + std::fabs(halfAy * Ay.Dot(Bz)) + std::fabs(halfAz * Az.Dot(Bz)))) {
1098 return false;
1099 }
1100
1101
1102
1103 if ((std::fabs(T.Dot(Az) * Ay.Dot(Bx) - T.Dot(Ay) * Az.Dot(Bx))) >
1104 (std::fabs(halfAy * Az.Dot(Bx)) + std::fabs(halfAz * Ay.Dot(Bx)) + std::fabs(halfBy * Ax.Dot(Bz)) +
1105 std::fabs(halfBz * Ax.Dot(By)))) {
1106 return false;
1107 }
1108
1109
1110
1111 if ((std::fabs(T.Dot(Az) * Ay.Dot(By) - T.Dot(Ay) * Az.Dot(By))) >
1112 (std::fabs(halfAy * Az.Dot(By)) + std::fabs(halfAz * Ay.Dot(By)) + std::fabs(halfBx * Ax.Dot(Bz)) +
1113 std::fabs(halfBz * Ax.Dot(Bx)))) {
1114 return false;
1115 }
1116
1117
1118
1119 if ((std::fabs(T.Dot(Az) * Ay.Dot(Bz) - T.Dot(Ay) * Az.Dot(Bz))) >
1120 (std::fabs(halfAy * Az.Dot(Bz)) + std::fabs(halfAz * Ay.Dot(Bz)) + std::fabs(halfBx * Ax.Dot(By)) +
1121 std::fabs(halfBy * Ax.Dot(Bx)))) {
1122 return false;
1123 }
1124
1125
1126
1127 if ((std::fabs(T.Dot(Ax) * Az.Dot(Bx) - T.Dot(Az) * Ax.Dot(Bx))) >
1128 (std::fabs(halfAx * Az.Dot(Bx)) + std::fabs(halfAz * Ax.Dot(Bx)) + std::fabs(halfBy * Ay.Dot(Bz)) +
1129 std::fabs(halfBz * Ay.Dot(By)))) {
1130 return false;
1131 }
1132
1133
1134
1135 if ((std::fabs(T.Dot(Ax) * Az.Dot(By) - T.Dot(Az) * Ax.Dot(By))) >
1136 (std::fabs(halfAx * Az.Dot(By)) + std::fabs(halfAz * Ax.Dot(By)) + std::fabs(halfBx * Ay.Dot(Bz)) +
1137 std::fabs(halfBz * Ay.Dot(Bx)))) {
1138 return false;
1139 }
1140
1141
1142
1143 if ((std::fabs(T.Dot(Ax) * Az.Dot(Bz) - T.Dot(Az) * Ax.Dot(Bz))) >
1144 (std::fabs(halfAx * Az.Dot(Bz)) + std::fabs(halfAz * Ax.Dot(Bz)) + std::fabs(halfBx * Ay.Dot(By)) +
1145 std::fabs(halfBy * Ay.Dot(Bx)))) {
1146 return false;
1147 }
1148
1149
1150
1151 if ((std::fabs(T.Dot(Ay) * Ax.Dot(Bx) - T.Dot(Ax) * Ay.Dot(Bx))) >
1152 (std::fabs(halfAx * Ay.Dot(Bx)) + std::fabs(halfAy * Ax.Dot(Bx)) + std::fabs(halfBy * Az.Dot(Bz)) +
1153 std::fabs(halfBz * Az.Dot(By)))) {
1154 return false;
1155 }
1156
1157
1158
1159 if ((std::fabs(T.Dot(Ay) * Ax.Dot(By) - T.Dot(Ax) * Ay.Dot(By))) >
1160 (std::fabs(halfAx * Ay.Dot(By)) + std::fabs(halfAy * Ax.Dot(By)) + std::fabs(halfBx * Az.Dot(Bz)) +
1161 std::fabs(halfBz * Az.Dot(Bx)))) {
1162 return false;
1163 }
1164
1165
1166
1167 if ((std::fabs(T.Dot(Ay) * Ax.Dot(Bz) - T.Dot(Ax) * Ay.Dot(Bz))) >
1168 (std::fabs(halfAx * Ay.Dot(Bz)) + std::fabs(halfAy * Ax.Dot(Bz)) + std::fabs(halfBx * Az.Dot(By)) +
1169 std::fabs(halfBy * Az.Dot(Bx)))) {
1170 return false;
1171 }
1172
1173 return true;
1174 }
1175
1176
1177
1178
1179
1180 template <typename T>
1181 void GenerateRegularSurfacePointsOnBox(Vector3D<T> const &lower, Vector3D<T> const &upper, int pointsperline,
1182 std::vector<Vector3D<T>> &points)
1183 {
1184 const auto lengthvector = upper - lower;
1185 const auto delta = lengthvector / (1. * pointsperline);
1186
1187
1188 for (int ny = 0; ny < pointsperline; ++ny) {
1189 const auto y = lower.y() + delta.y() * ny;
1190 for (int nz = 0; nz < pointsperline; ++nz) {
1191 const auto z = lower.z() + delta.z() * nz;
1192 Vector3D<T> p1(lower.x(), y, z);
1193 Vector3D<T> p2(upper.x(), y, z);
1194 points.push_back(p1);
1195 points.push_back(p2);
1196 }
1197 }
1198
1199 for (int nx = 0; nx < pointsperline; ++nx) {
1200 const auto x = lower.x() + delta.x() * nx;
1201 for (int nz = 0; nz < pointsperline; ++nz) {
1202 const auto z = lower.z() + delta.z() * nz;
1203 Vector3D<T> p1(x, lower.y(), z);
1204 Vector3D<T> p2(x, upper.y(), z);
1205 points.push_back(p1);
1206 points.push_back(p2);
1207 }
1208 }
1209
1210 for (int nx = 0; nx < pointsperline; ++nx) {
1211 const auto x = lower.x() + delta.x() * nx;
1212 for (int ny = 0; ny < pointsperline; ++ny) {
1213 const auto y = lower.y() + delta.y() * ny;
1214 Vector3D<T> p1(x, y, lower.z());
1215 Vector3D<T> p2(x, y, upper.z());
1216 points.push_back(p1);
1217 points.push_back(p2);
1218 }
1219 }
1220 points.push_back(upper);
1221 }
1222
1223 }
1224 }
1225 }
1226
1227 #endif