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