Geant4 10.7.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4BoundingEnvelope Class Reference

#include <G4BoundingEnvelope.hh>

Public Member Functions

 G4BoundingEnvelope (const G4ThreeVector &pMin, const G4ThreeVector &pMax)
 
 G4BoundingEnvelope (const std::vector< const G4ThreeVectorList * > &polygons)
 
 G4BoundingEnvelope (const G4ThreeVector &pMin, const G4ThreeVector &pMax, const std::vector< const G4ThreeVectorList * > &polygons)
 
 ~G4BoundingEnvelope ()
 
G4bool BoundingBoxVsVoxelLimits (const EAxis pAxis, const G4VoxelLimits &pVoxelLimits, const G4Transform3D &pTransform3D, G4double &pMin, G4double &pMax) const
 
G4bool CalculateExtent (const EAxis pAxis, const G4VoxelLimits &pVoxelLimits, const G4Transform3D &pTransform3D, G4double &pMin, G4double &pMax) const
 

Detailed Description

Definition at line 58 of file G4BoundingEnvelope.hh.

Constructor & Destructor Documentation

◆ G4BoundingEnvelope() [1/3]

G4BoundingEnvelope::G4BoundingEnvelope ( const G4ThreeVector pMin,
const G4ThreeVector pMax 
)

Definition at line 44 of file G4BoundingEnvelope.cc.

46 : fMin(pMin), fMax(pMax)
47{
48 // Check correctness of bounding box
49 //
50 CheckBoundingBox();
51}

◆ G4BoundingEnvelope() [2/3]

G4BoundingEnvelope::G4BoundingEnvelope ( const std::vector< const G4ThreeVectorList * > &  polygons)

Definition at line 57 of file G4BoundingEnvelope.cc.

59 : fPolygons(&polygons)
60{
61 // Check correctness of polygons
62 //
63 CheckBoundingPolygons();
64
65 // Set bounding box
66 //
67 G4double xmin = kInfinity, ymin = kInfinity, zmin = kInfinity;
68 G4double xmax = -kInfinity, ymax = -kInfinity, zmax = -kInfinity;
69 for (auto ibase = fPolygons->cbegin(); ibase != fPolygons->cend(); ++ibase)
70 {
71 for (auto ipoint = (*ibase)->cbegin(); ipoint != (*ibase)->cend(); ++ipoint)
72 {
73 G4double x = ipoint->x();
74 if (x < xmin) xmin = x;
75 if (x > xmax) xmax = x;
76 G4double y = ipoint->y();
77 if (y < ymin) ymin = y;
78 if (y > ymax) ymax = y;
79 G4double z = ipoint->z();
80 if (z < zmin) zmin = z;
81 if (z > zmax) zmax = z;
82 }
83 }
84 fMin.set(xmin,ymin,zmin);
85 fMax.set(xmax,ymax,zmax);
86
87 // Check correctness of bounding box
88 //
89 CheckBoundingBox();
90}
double G4double
Definition: G4Types.hh:83
void set(double x, double y, double z)

◆ G4BoundingEnvelope() [3/3]

G4BoundingEnvelope::G4BoundingEnvelope ( const G4ThreeVector pMin,
const G4ThreeVector pMax,
const std::vector< const G4ThreeVectorList * > &  polygons 
)

Definition at line 96 of file G4BoundingEnvelope.cc.

100 : fMin(pMin), fMax(pMax), fPolygons(&polygons)
101{
102 // Check correctness of bounding box and polygons
103 //
104 CheckBoundingBox();
105 CheckBoundingPolygons();
106}

◆ ~G4BoundingEnvelope()

G4BoundingEnvelope::~G4BoundingEnvelope ( )

Definition at line 112 of file G4BoundingEnvelope.cc.

113{
114}

Member Function Documentation

◆ BoundingBoxVsVoxelLimits()

G4bool G4BoundingEnvelope::BoundingBoxVsVoxelLimits ( const EAxis  pAxis,
const G4VoxelLimits pVoxelLimits,
const G4Transform3D pTransform3D,
G4double pMin,
G4double pMax 
) const

Definition at line 188 of file G4BoundingEnvelope.cc.

193{
194 pMin = kInfinity;
195 pMax = -kInfinity;
196 G4double xminlim = pVoxelLimits.GetMinXExtent();
197 G4double xmaxlim = pVoxelLimits.GetMaxXExtent();
198 G4double yminlim = pVoxelLimits.GetMinYExtent();
199 G4double ymaxlim = pVoxelLimits.GetMaxYExtent();
200 G4double zminlim = pVoxelLimits.GetMinZExtent();
201 G4double zmaxlim = pVoxelLimits.GetMaxZExtent();
202
203 // Special case of pure translation
204 //
205 if (pTransform3D.xx()==1 && pTransform3D.yy()==1 && pTransform3D.zz()==1)
206 {
207 G4double xmin = fMin.x() + pTransform3D.dx();
208 G4double xmax = fMax.x() + pTransform3D.dx();
209 G4double ymin = fMin.y() + pTransform3D.dy();
210 G4double ymax = fMax.y() + pTransform3D.dy();
211 G4double zmin = fMin.z() + pTransform3D.dz();
212 G4double zmax = fMax.z() + pTransform3D.dz();
213
214 if (xmin-kCarTolerance > xmaxlim) return true;
215 if (xmax+kCarTolerance < xminlim) return true;
216 if (ymin-kCarTolerance > ymaxlim) return true;
217 if (ymax+kCarTolerance < yminlim) return true;
218 if (zmin-kCarTolerance > zmaxlim) return true;
219 if (zmax+kCarTolerance < zminlim) return true;
220
221 if (xmin >= xminlim && xmax <= xmaxlim &&
222 ymin >= yminlim && ymax <= ymaxlim &&
223 zmin >= zminlim && zmax <= zmaxlim)
224 {
225 if (pAxis == kXAxis)
226 {
227 pMin = (xmin-kCarTolerance < xminlim) ? xminlim : xmin;
228 pMax = (xmax+kCarTolerance > xmaxlim) ? xmaxlim : xmax;
229 }
230 else if (pAxis == kYAxis)
231 {
232 pMin = (ymin-kCarTolerance < yminlim) ? yminlim : ymin;
233 pMax = (ymax+kCarTolerance > ymaxlim) ? ymaxlim : ymax;
234 }
235 else if (pAxis == kZAxis)
236 {
237 pMin = (zmin-kCarTolerance < zminlim) ? zminlim : zmin;
238 pMax = (zmax+kCarTolerance > zmaxlim) ? zmaxlim : zmax;
239 }
240 pMin -= kCarTolerance;
241 pMax += kCarTolerance;
242 return true;
243 }
244 }
245
246 // Find max scale factor of the transformation, set delta
247 // equal to kCarTolerance multiplied by the scale factor
248 //
249 G4double scale = FindScaleFactor(pTransform3D);
250 G4double delta = kCarTolerance*scale;
251
252 // Set the sphere surrounding the bounding box
253 //
254 G4Point3D center = pTransform3D*G4Point3D(0.5*(fMin+fMax));
255 G4double radius = 0.5*scale*(fMax-fMin).mag() + delta;
256
257 // Check if the sphere surrounding the bounding box is outside
258 // the voxel limits
259 //
260 if (center.x()-radius > xmaxlim) return true;
261 if (center.y()-radius > ymaxlim) return true;
262 if (center.z()-radius > zmaxlim) return true;
263 if (center.x()+radius < xminlim) return true;
264 if (center.y()+radius < yminlim) return true;
265 if (center.z()+radius < zminlim) return true;
266 return false;
267}
const G4double kCarTolerance
HepGeom::Point3D< G4double > G4Point3D
Definition: G4Point3D.hh:34
double z() const
double x() const
double y() const
G4double GetMinZExtent() const
G4double GetMaxYExtent() const
G4double GetMaxZExtent() const
G4double GetMinYExtent() const
G4double GetMinXExtent() const
G4double GetMaxXExtent() const
double dy() const
Definition: Transform3D.h:287
double zz() const
Definition: Transform3D.h:281
double dz() const
Definition: Transform3D.h:290
double dx() const
Definition: Transform3D.h:284
double xx() const
Definition: Transform3D.h:257
double yy() const
Definition: Transform3D.h:269
@ kYAxis
Definition: geomdefs.hh:56
@ kXAxis
Definition: geomdefs.hh:55
@ kZAxis
Definition: geomdefs.hh:57

Referenced by G4Cons::CalculateExtent(), G4CutTubs::CalculateExtent(), G4Orb::CalculateExtent(), G4Para::CalculateExtent(), G4Torus::CalculateExtent(), G4Trap::CalculateExtent(), G4Trd::CalculateExtent(), G4Tubs::CalculateExtent(), G4EllipticalCone::CalculateExtent(), G4EllipticalTube::CalculateExtent(), G4ExtrudedSolid::CalculateExtent(), G4GenericPolycone::CalculateExtent(), G4GenericTrap::CalculateExtent(), G4Polycone::CalculateExtent(), G4Polyhedra::CalculateExtent(), G4TessellatedSolid::CalculateExtent(), and G4Tet::CalculateExtent().

◆ CalculateExtent()

G4bool G4BoundingEnvelope::CalculateExtent ( const EAxis  pAxis,
const G4VoxelLimits pVoxelLimits,
const G4Transform3D pTransform3D,
G4double pMin,
G4double pMax 
) const

Definition at line 274 of file G4BoundingEnvelope.cc.

278{
279 pMin = kInfinity;
280 pMax = -kInfinity;
281 G4double xminlim = pVoxelLimits.GetMinXExtent();
282 G4double xmaxlim = pVoxelLimits.GetMaxXExtent();
283 G4double yminlim = pVoxelLimits.GetMinYExtent();
284 G4double ymaxlim = pVoxelLimits.GetMaxYExtent();
285 G4double zminlim = pVoxelLimits.GetMinZExtent();
286 G4double zmaxlim = pVoxelLimits.GetMaxZExtent();
287
288 // Special case of pure translation
289 //
290 if (pTransform3D.xx()==1 && pTransform3D.yy()==1 && pTransform3D.zz()==1)
291 {
292 G4double xmin = fMin.x() + pTransform3D.dx();
293 G4double xmax = fMax.x() + pTransform3D.dx();
294 G4double ymin = fMin.y() + pTransform3D.dy();
295 G4double ymax = fMax.y() + pTransform3D.dy();
296 G4double zmin = fMin.z() + pTransform3D.dz();
297 G4double zmax = fMax.z() + pTransform3D.dz();
298
299 if (xmin-kCarTolerance > xmaxlim) return false;
300 if (xmax+kCarTolerance < xminlim) return false;
301 if (ymin-kCarTolerance > ymaxlim) return false;
302 if (ymax+kCarTolerance < yminlim) return false;
303 if (zmin-kCarTolerance > zmaxlim) return false;
304 if (zmax+kCarTolerance < zminlim) return false;
305
306 if (fPolygons == nullptr)
307 {
308 if (pAxis == kXAxis)
309 {
310 pMin = (xmin-kCarTolerance < xminlim) ? xminlim : xmin;
311 pMax = (xmax+kCarTolerance > xmaxlim) ? xmaxlim : xmax;
312 }
313 else if (pAxis == kYAxis)
314 {
315 pMin = (ymin-kCarTolerance < yminlim) ? yminlim : ymin;
316 pMax = (ymax+kCarTolerance > ymaxlim) ? ymaxlim : ymax;
317 }
318 else if (pAxis == kZAxis)
319 {
320 pMin = (zmin-kCarTolerance < zminlim) ? zminlim : zmin;
321 pMax = (zmax+kCarTolerance > zmaxlim) ? zmaxlim : zmax;
322 }
323 pMin -= kCarTolerance;
324 pMax += kCarTolerance;
325 return true;
326 }
327 }
328
329 // Find max scale factor of the transformation, set delta
330 // equal to kCarTolerance multiplied by the scale factor
331 //
332 G4double scale = FindScaleFactor(pTransform3D);
333 G4double delta = kCarTolerance*scale;
334
335 // Set the sphere surrounding the bounding box
336 //
337 G4Point3D center = pTransform3D*G4Point3D(0.5*(fMin+fMax));
338 G4double radius = 0.5*scale*(fMax-fMin).mag() + delta;
339
340 // Check if the sphere surrounding the bounding box is within
341 // the voxel limits, if so then transform only one coordinate
342 //
343 if (center.x()-radius >= xminlim && center.x()+radius <= xmaxlim &&
344 center.y()-radius >= yminlim && center.y()+radius <= ymaxlim &&
345 center.z()-radius >= zminlim && center.z()+radius <= zmaxlim )
346 {
347 G4double cx, cy, cz, cd;
348 if (pAxis == kXAxis)
349 {
350 cx = pTransform3D.xx();
351 cy = pTransform3D.xy();
352 cz = pTransform3D.xz();
353 cd = pTransform3D.dx();
354 }
355 else if (pAxis == kYAxis)
356 {
357 cx = pTransform3D.yx();
358 cy = pTransform3D.yy();
359 cz = pTransform3D.yz();
360 cd = pTransform3D.dy();
361 }
362 else if (pAxis == kZAxis)
363 {
364 cx = pTransform3D.zx();
365 cy = pTransform3D.zy();
366 cz = pTransform3D.zz();
367 cd = pTransform3D.dz();
368 }
369 else
370 {
371 cx = cy = cz = cd = kInfinity;
372 }
373 G4double emin = kInfinity, emax = -kInfinity;
374 if (fPolygons == nullptr)
375 {
376 G4double coor;
377 coor = cx*fMin.x() + cy*fMin.y() + cz*fMin.z() + cd;
378 if (coor < emin) emin = coor;
379 if (coor > emax) emax = coor;
380 coor = cx*fMax.x() + cy*fMin.y() + cz*fMin.z() + cd;
381 if (coor < emin) emin = coor;
382 if (coor > emax) emax = coor;
383 coor = cx*fMax.x() + cy*fMax.y() + cz*fMin.z() + cd;
384 if (coor < emin) emin = coor;
385 if (coor > emax) emax = coor;
386 coor = cx*fMin.x() + cy*fMax.y() + cz*fMin.z() + cd;
387 if (coor < emin) emin = coor;
388 if (coor > emax) emax = coor;
389 coor = cx*fMin.x() + cy*fMin.y() + cz*fMax.z() + cd;
390 if (coor < emin) emin = coor;
391 if (coor > emax) emax = coor;
392 coor = cx*fMax.x() + cy*fMin.y() + cz*fMax.z() + cd;
393 if (coor < emin) emin = coor;
394 if (coor > emax) emax = coor;
395 coor = cx*fMax.x() + cy*fMax.y() + cz*fMax.z() + cd;
396 if (coor < emin) emin = coor;
397 if (coor > emax) emax = coor;
398 coor = cx*fMin.x() + cy*fMax.y() + cz*fMax.z() + cd;
399 if (coor < emin) emin = coor;
400 if (coor > emax) emax = coor;
401 }
402 else
403 {
404 for (auto ibase=fPolygons->cbegin(); ibase!=fPolygons->cend(); ++ibase)
405 {
406 for (auto ipoint=(*ibase)->cbegin(); ipoint!=(*ibase)->cend(); ++ipoint)
407 {
408 G4double coor = ipoint->x()*cx + ipoint->y()*cy + ipoint->z()*cz + cd;
409 if (coor < emin) emin = coor;
410 if (coor > emax) emax = coor;
411 }
412 }
413 }
414 pMin = emin - delta;
415 pMax = emax + delta;
416 return true;
417 }
418
419 // Check if the sphere surrounding the bounding box is outside
420 // the voxel limits
421 //
422 if (center.x()-radius > xmaxlim) return false;
423 if (center.y()-radius > ymaxlim) return false;
424 if (center.z()-radius > zmaxlim) return false;
425 if (center.x()+radius < xminlim) return false;
426 if (center.y()+radius < yminlim) return false;
427 if (center.z()+radius < zminlim) return false;
428
429 // Allocate memory for transformed polygons
430 //
431 G4int nbases = (fPolygons == 0) ? 2 : fPolygons->size();
432 std::vector<G4Polygon3D*> bases(nbases);
433 if (fPolygons == nullptr)
434 {
435 bases[0] = new G4Polygon3D(4);
436 bases[1] = new G4Polygon3D(4);
437 }
438 else
439 {
440 for (G4int i=0; i<nbases; ++i)
441 {
442 bases[i] = new G4Polygon3D((*fPolygons)[i]->size());
443 }
444 }
445
446 // Transform vertices
447 //
448 TransformVertices(pTransform3D, bases);
449
450 // Create adjusted G4VoxelLimits box. New limits are extended by
451 // delta, kCarTolerance multiplied by max scale factor of
452 // the transformation
453 //
454 EAxis axis[] = { kXAxis,kYAxis,kZAxis };
455 G4VoxelLimits limits; // default is unlimited
456 for (auto i=0; i<3; ++i)
457 {
458 if (pVoxelLimits.IsLimited(axis[i]))
459 {
460 G4double emin = pVoxelLimits.GetMinExtent(axis[i]) - delta;
461 G4double emax = pVoxelLimits.GetMaxExtent(axis[i]) + delta;
462 limits.AddLimit(axis[i], emin, emax);
463 }
464 }
465
466 // Main loop along the set of prisms
467 //
468 G4Segment3D extent;
469 extent.first = G4Point3D( kInfinity, kInfinity, kInfinity);
470 extent.second = G4Point3D(-kInfinity,-kInfinity,-kInfinity);
471 for (G4int k=0; k<nbases-1; ++k)
472 {
473 // Find bounding box of current prism
474 G4Polygon3D* baseA = bases[k];
475 G4Polygon3D* baseB = bases[k+1];
476 G4Segment3D prismAABB;
477 GetPrismAABB(*baseA, *baseB, prismAABB);
478
479 // Check if prismAABB is completely within the voxel limits
480 if (prismAABB.first.x() >= limits.GetMinXExtent() &&
481 prismAABB.first.y() >= limits.GetMinYExtent() &&
482 prismAABB.first.z() >= limits.GetMinZExtent() &&
483 prismAABB.second.x()<= limits.GetMaxXExtent() &&
484 prismAABB.second.y()<= limits.GetMaxYExtent() &&
485 prismAABB.second.z()<= limits.GetMaxZExtent())
486 {
487 if (extent.first.x() > prismAABB.first.x())
488 extent.first.setX( prismAABB.first.x() );
489 if (extent.first.y() > prismAABB.first.y())
490 extent.first.setY( prismAABB.first.y() );
491 if (extent.first.z() > prismAABB.first.z())
492 extent.first.setZ( prismAABB.first.z() );
493 if (extent.second.x() < prismAABB.second.x())
494 extent.second.setX(prismAABB.second.x());
495 if (extent.second.y() < prismAABB.second.y())
496 extent.second.setY(prismAABB.second.y());
497 if (extent.second.z() < prismAABB.second.z())
498 extent.second.setZ(prismAABB.second.z());
499 continue;
500 }
501
502 // Check if prismAABB is outside the voxel limits
503 if (prismAABB.first.x() > limits.GetMaxXExtent()) continue;
504 if (prismAABB.first.y() > limits.GetMaxYExtent()) continue;
505 if (prismAABB.first.z() > limits.GetMaxZExtent()) continue;
506 if (prismAABB.second.x() < limits.GetMinXExtent()) continue;
507 if (prismAABB.second.y() < limits.GetMinYExtent()) continue;
508 if (prismAABB.second.z() < limits.GetMinZExtent()) continue;
509
510 // Clip edges of the prism by adjusted G4VoxelLimits box
511 std::vector<G4Segment3D> vecEdges;
512 CreateListOfEdges(*baseA, *baseB, vecEdges);
513 if (ClipEdgesByVoxel(vecEdges, limits, extent)) continue;
514
515 // Some edges of the prism are completely outside of the voxel
516 // limits, clip selected edges (see bits) of adjusted G4VoxelLimits
517 // by the prism
518 G4int bits = 0x000;
519 if (limits.GetMinXExtent() < prismAABB.first.x())
520 bits |= 0x988; // 1001 1000 1000
521 if (limits.GetMaxXExtent() > prismAABB.second.x())
522 bits |= 0x622; // 0110 0010 0010
523
524 if (limits.GetMinYExtent() < prismAABB.first.y())
525 bits |= 0x311; // 0011 0001 0001
526 if (limits.GetMaxYExtent() > prismAABB.second.y())
527 bits |= 0xC44; // 1100 0100 0100
528
529 if (limits.GetMinZExtent() < prismAABB.first.z())
530 bits |= 0x00F; // 0000 0000 1111
531 if (limits.GetMaxZExtent() > prismAABB.second.z())
532 bits |= 0x0F0; // 0000 1111 0000
533 if (bits == 0xFFF) continue;
534
535 std::vector<G4Plane3D> vecPlanes;
536 CreateListOfPlanes(*baseA, *baseB, vecPlanes);
537 ClipVoxelByPlanes(bits, limits, vecPlanes, prismAABB, extent);
538 } // End of the main loop
539
540 // Free memory
541 //
542 for (G4int i=0; i<nbases; ++i) { delete bases[i]; bases[i] = 0; }
543
544 // Final adjustment of the extent
545 //
546 G4double emin = 0, emax = 0;
547 if (pAxis == kXAxis) { emin = extent.first.x(); emax = extent.second.x(); }
548 if (pAxis == kYAxis) { emin = extent.first.y(); emax = extent.second.y(); }
549 if (pAxis == kZAxis) { emin = extent.first.z(); emax = extent.second.z(); }
550
551 if (emin > emax) return false;
552 emin -= delta;
553 emax += delta;
554 G4double minlim = pVoxelLimits.GetMinExtent(pAxis);
555 G4double maxlim = pVoxelLimits.GetMaxExtent(pAxis);
556 pMin = (emin < minlim) ? minlim-kCarTolerance : emin;
557 pMax = (emax > maxlim) ? maxlim+kCarTolerance : emax;
558 return true;
559}
std::pair< G4Point3D, G4Point3D > G4Segment3D
std::vector< G4Point3D > G4Polygon3D
int G4int
Definition: G4Types.hh:85
G4double GetMinExtent(const EAxis pAxis) const
void AddLimit(const EAxis pAxis, const G4double pMin, const G4double pMax)
G4double GetMaxExtent(const EAxis pAxis) const
G4bool IsLimited() const
double yz() const
Definition: Transform3D.h:272
double xy() const
Definition: Transform3D.h:260
double zx() const
Definition: Transform3D.h:275
double yx() const
Definition: Transform3D.h:266
double zy() const
Definition: Transform3D.h:278
double xz() const
Definition: Transform3D.h:263
EAxis
Definition: geomdefs.hh:54

Referenced by G4MultiUnion::CalculateExtent(), G4ScaledSolid::CalculateExtent(), G4Box::CalculateExtent(), G4Cons::CalculateExtent(), G4CutTubs::CalculateExtent(), G4Orb::CalculateExtent(), G4Para::CalculateExtent(), G4Sphere::CalculateExtent(), G4Torus::CalculateExtent(), G4Trap::CalculateExtent(), G4Trd::CalculateExtent(), G4Tubs::CalculateExtent(), G4Ellipsoid::CalculateExtent(), G4EllipticalCone::CalculateExtent(), G4EllipticalTube::CalculateExtent(), G4ExtrudedSolid::CalculateExtent(), G4GenericPolycone::CalculateExtent(), G4GenericTrap::CalculateExtent(), G4Hype::CalculateExtent(), G4Paraboloid::CalculateExtent(), G4Polycone::CalculateExtent(), G4Polyhedra::CalculateExtent(), G4TessellatedSolid::CalculateExtent(), G4Tet::CalculateExtent(), G4TwistedTubs::CalculateExtent(), and G4VTwistedFaceted::CalculateExtent().


The documentation for this class was generated from the following files: