Geant4  10.01.p02
G4VoxelNavigation.cc
Go to the documentation of this file.
1 //
2 // ********************************************************************
3 // * License and Disclaimer *
4 // * *
5 // * The Geant4 software is copyright of the Copyright Holders of *
6 // * the Geant4 Collaboration. It is provided under the terms and *
7 // * conditions of the Geant4 Software License, included in the file *
8 // * LICENSE and available at http://cern.ch/geant4/license . These *
9 // * include a list of copyright holders. *
10 // * *
11 // * Neither the authors of this software system, nor their employing *
12 // * institutes,nor the agencies providing financial support for this *
13 // * work make any representation or warranty, express or implied, *
14 // * regarding this software system or assume any liability for its *
15 // * use. Please see the license in the file LICENSE and URL above *
16 // * for the full disclaimer and the limitation of liability. *
17 // * *
18 // * This code implementation is the result of the scientific and *
19 // * technical work of the GEANT4 collaboration. *
20 // * By using, copying, modifying or distributing the software (or *
21 // * any work based on the software) you agree to acknowledge its *
22 // * use in resulting scientific publications, and indicate your *
23 // * acceptance of all terms of the Geant4 Software license. *
24 // ********************************************************************
25 //
26 //
27 // $Id: G4VoxelNavigation.cc 90836 2015-06-10 09:31:06Z gcosmo $
28 //
29 //
30 // class G4VoxelNavigation Implementation
31 //
32 // Author: P.Kent, 1996
33 //
34 // --------------------------------------------------------------------
35 #include <ostream>
36 
37 #include "G4VoxelNavigation.hh"
38 #include "G4GeometryTolerance.hh"
39 #include "G4VoxelSafety.hh"
40 
42 
43 #ifdef G4DEBUG_NAVIGATION
44 static int debugVerboseLevel= 5; // Reports most about daughter volumes
45 #endif
46 
47 // ********************************************************************
48 // Constructor
49 // ********************************************************************
50 //
52  : fBList(), fVoxelDepth(-1),
53  fVoxelAxisStack(kNavigatorVoxelStackMax,kXAxis),
54  fVoxelNoSlicesStack(kNavigatorVoxelStackMax,0),
55  fVoxelSliceWidthStack(kNavigatorVoxelStackMax,0.),
56  fVoxelNodeNoStack(kNavigatorVoxelStackMax,0),
57  fVoxelHeaderStack(kNavigatorVoxelStackMax,(G4SmartVoxelHeader*)0),
58  fVoxelNode(0), fpVoxelSafety(0), fCheck(false), fBestSafety(false)
59 {
60  fLogger = new G4NavigationLogger("G4VoxelNavigation");
62 
63 #ifdef G4DEBUG_NAVIGATION
64  SetVerboseLevel(debugVerboseLevel); // Reports most about daughter volumes
65 #endif
66 }
67 
68 // ********************************************************************
69 // Destructor
70 // ********************************************************************
71 //
73 {
74  delete fpVoxelSafety;
75  delete fLogger;
76 }
77 
78 // ********************************************************************
79 // ComputeStep
80 // ********************************************************************
81 //
84  const G4ThreeVector& localDirection,
85  const G4double currentProposedStepLength,
86  G4double& newSafety,
87  G4NavigationHistory& history,
88  G4bool& validExitNormal,
89  G4ThreeVector& exitNormal,
90  G4bool& exiting,
91  G4bool& entering,
92  G4VPhysicalVolume *(*pBlockedPhysical),
93  G4int& blockedReplicaNo )
94 {
95  G4VPhysicalVolume *motherPhysical, *samplePhysical, *blockedExitedVol=0;
96  G4LogicalVolume *motherLogical;
97  G4VSolid *motherSolid;
98  G4ThreeVector sampleDirection;
99  G4double ourStep=currentProposedStepLength, ourSafety;
100  G4double motherSafety, motherStep=DBL_MAX;
101  G4int localNoDaughters, sampleNo;
102 
103  G4bool initialNode, noStep;
104  G4SmartVoxelNode *curVoxelNode;
105  G4int curNoVolumes, contentNo;
106  G4double voxelSafety;
107 
108  motherPhysical = history.GetTopVolume();
109  motherLogical = motherPhysical->GetLogicalVolume();
110  motherSolid = motherLogical->GetSolid();
111 
112  //
113  // Compute mother safety
114  //
115 
116  motherSafety = motherSolid->DistanceToOut(localPoint);
117  ourSafety = motherSafety; // Working isotropic safety
118 
119 #ifdef G4VERBOSE
120  if ( fCheck )
121  {
122  fLogger->PreComputeStepLog (motherPhysical, motherSafety, localPoint);
123  }
124 #endif
125 
126  //
127  // Compute daughter safeties & intersections
128  //
129 
130  // Exiting normal optimisation
131  //
132  if ( exiting && validExitNormal )
133  {
134  if ( localDirection.dot(exitNormal)>=kMinExitingNormalCosine )
135  {
136  // Block exited daughter volume
137  //
138  blockedExitedVol = *pBlockedPhysical;
139  ourSafety = 0;
140  }
141  }
142  exiting = false;
143  entering = false;
144 
145  // For extra checking, get the distance to Mother early !!
146  G4bool motherValidExitNormal= false;
147  G4ThreeVector motherExitNormal(0.0, 0.0, 0.0);
148 
149 #ifdef G4VERBOSE
150  if ( fCheck )
151  {
152  // Compute early -- a) for validity
153  // b) to check against answer of daughters!
154  motherStep = motherSolid->DistanceToOut(localPoint,
155  localDirection,
156  true,
157  &motherValidExitNormal,
158  &motherExitNormal);
159 
160  fLogger->PostComputeStepLog(motherSolid, localPoint, localDirection,
161  motherStep, motherSafety);
162 
163  if( (motherStep >= kInfinity) || (motherStep < 0.0) )
164  {
165  // Error - indication of being outside solid !!
166  fLogger->ReportOutsideMother(localPoint, localDirection, motherPhysical);
167 
168  ourStep = 0.0;
169 
170  exiting= true;
171  entering= false;
172 
173  // validExitNormal= motherValidExitNormal;
174  // exitNormal= motherExitNormal;
175  // Makes sense and is useful only if the point is very close ...
176  // Alternatives: i) validExitNormal= false;
177  // ii) Check safety from outside and choose !!
178  validExitNormal= false;
179 
180  *pBlockedPhysical= 0; // or motherPhysical ?
181  blockedReplicaNo= 0; // or motherReplicaNumber ?
182 
183  newSafety= 0.0;
184  return ourStep;
185  }
186  }
187 #endif
188 
189  localNoDaughters = motherLogical->GetNoDaughters();
190 
191  fBList.Enlarge(localNoDaughters);
192  fBList.Reset();
193 
194  initialNode = true;
195  noStep = true;
196 
197  while (noStep)
198  {
199  curVoxelNode = fVoxelNode;
200  curNoVolumes = curVoxelNode->GetNoContained();
201  for (contentNo=curNoVolumes-1; contentNo>=0; contentNo--)
202  {
203  sampleNo = curVoxelNode->GetVolume(contentNo);
204  if ( !fBList.IsBlocked(sampleNo) )
205  {
206  fBList.BlockVolume(sampleNo);
207  samplePhysical = motherLogical->GetDaughter(sampleNo);
208  if ( samplePhysical!=blockedExitedVol )
209  {
210  G4AffineTransform sampleTf(samplePhysical->GetRotation(),
211  samplePhysical->GetTranslation());
212  sampleTf.Invert();
213  const G4ThreeVector samplePoint =
214  sampleTf.TransformPoint(localPoint);
215  const G4VSolid *sampleSolid =
216  samplePhysical->GetLogicalVolume()->GetSolid();
217  const G4double sampleSafety =
218  sampleSolid->DistanceToIn(samplePoint);
219 
220  if ( sampleSafety<ourSafety )
221  {
222  ourSafety = sampleSafety;
223  }
224  if ( sampleSafety<=ourStep )
225  {
226  sampleDirection = sampleTf.TransformAxis(localDirection);
227  G4double sampleStep =
228  sampleSolid->DistanceToIn(samplePoint, sampleDirection);
229 #ifdef G4VERBOSE
230  if( fCheck )
231  {
232  fLogger->PrintDaughterLog(sampleSolid, samplePoint,
233  sampleSafety, true,
234  sampleDirection, sampleStep);
235  }
236 #endif
237  if ( sampleStep<=ourStep )
238  {
239  ourStep = sampleStep;
240  entering = true;
241  exiting = false;
242  *pBlockedPhysical = samplePhysical;
243  blockedReplicaNo = -1;
244 #ifdef G4VERBOSE
245  // Check to see that the resulting point is indeed in/on volume.
246  // This could be done only for successful candidate.
247  if ( fCheck )
248  {
249  fLogger->AlongComputeStepLog (sampleSolid, samplePoint,
250  sampleDirection, localDirection, sampleSafety, sampleStep);
251  }
252 #endif
253  }
254 #ifdef G4VERBOSE
255  if ( fCheck && ( sampleStep < kInfinity )
256  && ( sampleStep >= motherStep ) )
257  {
258  // The intersection point with the daughter is after the exit
259  // point from the mother volume. Double check this !!
260  fLogger->CheckDaughterEntryPoint(sampleSolid,
261  samplePoint, sampleDirection,
262  motherSolid,
263  localPoint, localDirection,
264  motherStep, sampleStep);
265  }
266 #endif
267  }
268 #ifdef G4VERBOSE
269  else // ie if sampleSafety > outStep
270  {
271  if( fCheck )
272  {
273  fLogger->PrintDaughterLog(sampleSolid, samplePoint,
274  sampleSafety, false,
275  G4ThreeVector(0.,0.,0.), -1.0 );
276  }
277  }
278 #endif
279  }
280  }
281  }
282  if (initialNode)
283  {
284  initialNode = false;
285  voxelSafety = ComputeVoxelSafety(localPoint);
286  if ( voxelSafety<ourSafety )
287  {
288  ourSafety = voxelSafety;
289  }
290  if ( currentProposedStepLength<ourSafety )
291  {
292  // Guaranteed physics limited
293  //
294  noStep = false;
295  entering = false;
296  exiting = false;
297  *pBlockedPhysical = 0;
298  ourStep = kInfinity;
299  }
300  else
301  {
302  //
303  // Compute mother intersection if required
304  //
305  if ( motherSafety<=ourStep )
306  {
307  if( !fCheck )
308  {
309  motherStep = motherSolid->DistanceToOut(localPoint, localDirection,
310  true, &motherValidExitNormal, &motherExitNormal);
311  }
312  // Not correct - unless mother limits step (see below)
313  // validExitNormal= motherValidExitNormal;
314  // exitNormal= motherExitNormal;
315 #ifdef G4VERBOSE
316  else // check_mode
317  {
318  fLogger->PostComputeStepLog(motherSolid, localPoint, localDirection,
319  motherStep, motherSafety);
320  if( motherValidExitNormal )
321  {
322  fLogger->CheckAndReportBadNormal(motherExitNormal,
323  localPoint, localDirection,
324  motherStep, motherSolid,
325  "From motherSolid::DistanceToOut" );
326  }
327  }
328 #endif
329  if( (motherStep >= kInfinity) || (motherStep < 0.0) )
330  {
331  // Error - indication of being outside solid !!
332  //
333  fLogger->ReportOutsideMother(localPoint, localDirection, motherPhysical);
334 
335  motherStep = 0.0;
336  ourStep = 0.0;
337  exiting = true;
338  entering = false;
339 
340  // validExitNormal= motherValidExitNormal;
341  // exitNormal= motherExitNormal;
342  // Useful only if the point is very close to surface
343  // => but it would need to be rotated to grand-mother ref frame !
344  validExitNormal= false;
345 
346  *pBlockedPhysical= 0; // or motherPhysical ?
347  blockedReplicaNo= 0; // or motherReplicaNumber ?
348 
349  newSafety= 0.0;
350  return ourStep;
351  }
352 
353  if ( motherStep<=ourStep )
354  {
355  ourStep = motherStep;
356  exiting = true;
357  entering = false;
358 
359  // Exit normal: Natural location to set these;confirmed short step
360  //
361  validExitNormal= motherValidExitNormal;
362  exitNormal= motherExitNormal;
363 
364  if ( validExitNormal )
365  {
366  const G4RotationMatrix *rot = motherPhysical->GetRotation();
367  if (rot)
368  {
369  exitNormal *= rot->inverse();
370  }
371  }
372  }
373  else
374  {
375  validExitNormal = false;
376  }
377  }
378  }
379  newSafety = ourSafety;
380  }
381  if (noStep)
382  {
383  noStep = LocateNextVoxel(localPoint, localDirection, ourStep);
384  }
385  } // end -while (noStep)- loop
386 
387  return ourStep;
388 }
389 
390 // ********************************************************************
391 // ComputeVoxelSafety
392 //
393 // Computes safety from specified point to voxel boundaries
394 // using already located point
395 // o collected boundaries for most derived level
396 // o adjacent boundaries for previous levels
397 // ********************************************************************
398 //
399 G4double
401 {
402  G4SmartVoxelHeader *curHeader;
403  G4double voxelSafety, curNodeWidth;
404  G4double curNodeOffset, minCurCommonDelta, maxCurCommonDelta;
405  G4int minCurNodeNoDelta, maxCurNodeNoDelta;
406  G4int localVoxelDepth, curNodeNo;
407  EAxis curHeaderAxis;
408 
409  localVoxelDepth = fVoxelDepth;
410 
411  curHeader = fVoxelHeaderStack[localVoxelDepth];
412  curHeaderAxis = fVoxelAxisStack[localVoxelDepth];
413  curNodeNo = fVoxelNodeNoStack[localVoxelDepth];
414  curNodeWidth = fVoxelSliceWidthStack[localVoxelDepth];
415 
416  // Compute linear intersection distance to boundaries of max/min
417  // to collected nodes at current level
418  //
419  curNodeOffset = curNodeNo*curNodeWidth;
420  maxCurNodeNoDelta = fVoxelNode->GetMaxEquivalentSliceNo()-curNodeNo;
421  minCurNodeNoDelta = curNodeNo-fVoxelNode->GetMinEquivalentSliceNo();
422  minCurCommonDelta = localPoint(curHeaderAxis)
423  - curHeader->GetMinExtent() - curNodeOffset;
424  maxCurCommonDelta = curNodeWidth-minCurCommonDelta;
425 
426  if ( minCurNodeNoDelta<maxCurNodeNoDelta )
427  {
428  voxelSafety = minCurNodeNoDelta*curNodeWidth;
429  voxelSafety += minCurCommonDelta;
430  }
431  else if (maxCurNodeNoDelta < minCurNodeNoDelta)
432  {
433  voxelSafety = maxCurNodeNoDelta*curNodeWidth;
434  voxelSafety += maxCurCommonDelta;
435  }
436  else // (maxCurNodeNoDelta == minCurNodeNoDelta)
437  {
438  voxelSafety = minCurNodeNoDelta*curNodeWidth;
439  voxelSafety += std::min(minCurCommonDelta,maxCurCommonDelta);
440  }
441 
442  // Compute isotropic safety to boundaries of previous levels
443  // [NOT to collected boundaries]
444  //
445  while ( (localVoxelDepth>0) && (voxelSafety>0) )
446  {
447  localVoxelDepth--;
448  curHeader = fVoxelHeaderStack[localVoxelDepth];
449  curHeaderAxis = fVoxelAxisStack[localVoxelDepth];
450  curNodeNo = fVoxelNodeNoStack[localVoxelDepth];
451  curNodeWidth = fVoxelSliceWidthStack[localVoxelDepth];
452  curNodeOffset = curNodeNo*curNodeWidth;
453  minCurCommonDelta = localPoint(curHeaderAxis)
454  - curHeader->GetMinExtent() - curNodeOffset;
455  maxCurCommonDelta = curNodeWidth-minCurCommonDelta;
456 
457  if ( minCurCommonDelta<voxelSafety )
458  {
459  voxelSafety = minCurCommonDelta;
460  }
461  if ( maxCurCommonDelta<voxelSafety )
462  {
463  voxelSafety = maxCurCommonDelta;
464  }
465  }
466  if ( voxelSafety<0 )
467  {
468  voxelSafety = 0;
469  }
470 
471  return voxelSafety;
472 }
473 
474 // ********************************************************************
475 // LocateNextVoxel
476 //
477 // Finds the next voxel from the current voxel and point
478 // in the specified direction
479 //
480 // Returns false if all voxels considered
481 // [current Step ends inside same voxel or leaves all voxels]
482 // true otherwise
483 // [the information on the next voxel is put into the set of
484 // fVoxel* variables & "stacks"]
485 // ********************************************************************
486 //
487 G4bool
489  const G4ThreeVector& localDirection,
490  const G4double currentStep)
491 {
492  G4SmartVoxelHeader *workHeader=0, *newHeader=0;
493  G4SmartVoxelProxy *newProxy=0;
494  G4SmartVoxelNode *newVoxelNode=0;
495  G4ThreeVector targetPoint, voxelPoint;
496  G4double workNodeWidth, workMinExtent, workCoord;
497  G4double minVal, maxVal, newDistance=0.;
498  G4double newHeaderMin, newHeaderNodeWidth;
499  G4int depth=0, newDepth=0, workNodeNo=0, newNodeNo=0, newHeaderNoSlices=0;
500  EAxis workHeaderAxis, newHeaderAxis;
501  G4bool isNewVoxel=false;
502 
503  G4double currentDistance = currentStep;
504  static const G4double sigma = 0.5*G4GeometryTolerance::GetInstance()
506 
507  // Determine if end of Step within current voxel
508  //
509  for (depth=0; depth<fVoxelDepth; depth++)
510  {
511  targetPoint = localPoint+localDirection*currentDistance;
512  newDistance = currentDistance;
513  workHeader = fVoxelHeaderStack[depth];
514  workHeaderAxis = fVoxelAxisStack[depth];
515  workNodeNo = fVoxelNodeNoStack[depth];
516  workNodeWidth = fVoxelSliceWidthStack[depth];
517  workMinExtent = workHeader->GetMinExtent();
518  workCoord = targetPoint(workHeaderAxis);
519  minVal = workMinExtent+workNodeNo*workNodeWidth;
520 
521  if ( minVal<=workCoord+sigma )
522  {
523  maxVal = minVal+workNodeWidth;
524  if ( maxVal<=workCoord-sigma )
525  {
526  // Must consider next voxel
527  //
528  newNodeNo = workNodeNo+1;
529  newHeader = workHeader;
530  newDistance = (maxVal-localPoint(workHeaderAxis))
531  / localDirection(workHeaderAxis);
532  isNewVoxel = true;
533  newDepth = depth;
534  }
535  }
536  else
537  {
538  newNodeNo = workNodeNo-1;
539  newHeader = workHeader;
540  newDistance = (minVal-localPoint(workHeaderAxis))
541  / localDirection(workHeaderAxis);
542  isNewVoxel = true;
543  newDepth = depth;
544  }
545  currentDistance = newDistance;
546  }
547  targetPoint = localPoint+localDirection*currentDistance;
548 
549  // Check if end of Step within collected boundaries of current voxel
550  //
551  depth = fVoxelDepth;
552  {
553  workHeader = fVoxelHeaderStack[depth];
554  workHeaderAxis = fVoxelAxisStack[depth];
555  workNodeNo = fVoxelNodeNoStack[depth];
556  workNodeWidth = fVoxelSliceWidthStack[depth];
557  workMinExtent = workHeader->GetMinExtent();
558  workCoord = targetPoint(workHeaderAxis);
559  minVal = workMinExtent+fVoxelNode->GetMinEquivalentSliceNo()*workNodeWidth;
560 
561  if ( minVal<=workCoord+sigma )
562  {
563  maxVal = workMinExtent+(fVoxelNode->GetMaxEquivalentSliceNo()+1)
564  *workNodeWidth;
565  if ( maxVal<=workCoord-sigma )
566  {
567  newNodeNo = fVoxelNode->GetMaxEquivalentSliceNo()+1;
568  newHeader = workHeader;
569  newDistance = (maxVal-localPoint(workHeaderAxis))
570  / localDirection(workHeaderAxis);
571  isNewVoxel = true;
572  newDepth = depth;
573  }
574  }
575  else
576  {
577  newNodeNo = fVoxelNode->GetMinEquivalentSliceNo()-1;
578  newHeader = workHeader;
579  newDistance = (minVal-localPoint(workHeaderAxis))
580  / localDirection(workHeaderAxis);
581  isNewVoxel = true;
582  newDepth = depth;
583  }
584  currentDistance = newDistance;
585  }
586  if (isNewVoxel)
587  {
588  // Compute new voxel & adjust voxel stack
589  //
590  // newNodeNo=Candidate node no at
591  // newDepth =refinement depth of crossed voxel boundary
592  // newHeader=Header for crossed voxel
593  // newDistance=distance to crossed voxel boundary (along the track)
594  //
595  if ( (newNodeNo<0) || (newNodeNo>=newHeader->GetNoSlices()))
596  {
597  // Leaving mother volume
598  //
599  isNewVoxel = false;
600  }
601  else
602  {
603  // Compute intersection point on the least refined
604  // voxel boundary that is hit
605  //
606  voxelPoint = localPoint+localDirection*newDistance;
607  fVoxelNodeNoStack[newDepth] = newNodeNo;
608  fVoxelDepth = newDepth;
609  newVoxelNode = 0;
610  while ( !newVoxelNode )
611  {
612  newProxy = newHeader->GetSlice(newNodeNo);
613  if (newProxy->IsNode())
614  {
615  newVoxelNode = newProxy->GetNode();
616  }
617  else
618  {
619  fVoxelDepth++;
620  newHeader = newProxy->GetHeader();
621  newHeaderAxis = newHeader->GetAxis();
622  newHeaderNoSlices = newHeader->GetNoSlices();
623  newHeaderMin = newHeader->GetMinExtent();
624  newHeaderNodeWidth = (newHeader->GetMaxExtent()-newHeaderMin)
625  / newHeaderNoSlices;
626  newNodeNo = G4int( (voxelPoint(newHeaderAxis)-newHeaderMin)
627  / newHeaderNodeWidth );
628  // Rounding protection
629  //
630  if ( newNodeNo<0 )
631  {
632  newNodeNo=0;
633  }
634  else if ( newNodeNo>=newHeaderNoSlices )
635  {
636  newNodeNo = newHeaderNoSlices-1;
637  }
638  // Stack info for stepping
639  //
640  fVoxelAxisStack[fVoxelDepth] = newHeaderAxis;
641  fVoxelNoSlicesStack[fVoxelDepth] = newHeaderNoSlices;
642  fVoxelSliceWidthStack[fVoxelDepth] = newHeaderNodeWidth;
643  fVoxelNodeNoStack[fVoxelDepth] = newNodeNo;
644  fVoxelHeaderStack[fVoxelDepth] = newHeader;
645  }
646  }
647  fVoxelNode = newVoxelNode;
648  }
649  }
650  return isNewVoxel;
651 }
652 
653 // ********************************************************************
654 // ComputeSafety
655 //
656 // Calculates the isotropic distance to the nearest boundary from the
657 // specified point in the local coordinate system.
658 // The localpoint utilised must be within the current volume.
659 // ********************************************************************
660 //
661 G4double
663  const G4NavigationHistory& history,
664  const G4double maxLength)
665 {
666  G4VPhysicalVolume *motherPhysical, *samplePhysical;
667  G4LogicalVolume *motherLogical;
668  G4VSolid *motherSolid;
669  G4double motherSafety, ourSafety;
670  G4int sampleNo;
671  G4SmartVoxelNode *curVoxelNode;
672  G4int curNoVolumes, contentNo;
673  G4double voxelSafety;
674 
675  motherPhysical = history.GetTopVolume();
676  motherLogical = motherPhysical->GetLogicalVolume();
677  motherSolid = motherLogical->GetSolid();
678 
679  if( fBestSafety )
680  {
681  return fpVoxelSafety->ComputeSafety( localPoint,*motherPhysical,maxLength );
682  }
683 
684  //
685  // Compute mother safety
686  //
687 
688  motherSafety = motherSolid->DistanceToOut(localPoint);
689  ourSafety = motherSafety; // Working isotropic safety
690 
691  if( motherSafety == 0.0 )
692  {
693 #ifdef G4DEBUG_NAVIGATION
694  // Check that point is inside mother volume
695  EInside insideMother= motherSolid->Inside(localPoint);
696 
697  if( insideMother == kOutside )
698  {
699  G4ExceptionDescription message;
700  message << "Safety method called for location outside current Volume." << G4endl
701  << "Location for safety is Outside this volume. " << G4endl
702  << "The approximate distance to the solid "
703  << "(safety from outside) is: "
704  << motherSolid->DistanceToIn( localPoint ) << G4endl;
705  message << " Problem occurred with physical volume: "
706  << " Name: " << motherPhysical->GetName()
707  << " Copy No: " << motherPhysical->GetCopyNo() << G4endl
708  << " Local Point = " << localPoint << G4endl;
709  message << " Description of solid: " << G4endl
710  << *motherSolid << G4endl;
711  G4Exception("G4VoxelNavigation::ComputeSafety()", "GeomNav0003",
712  JustWarning, // FatalException,
713  message);
714  }
715 
716  // Following check is NOT for an issue - it is only for information
717  // It is allowed that a solid gives approximate safety - even zero.
718  //
719  if( insideMother == kInside ) // && fVerbose )
720  {
721  G4ExceptionDescription messageIn;
722 
723  messageIn << " Point is Inside, but safety is Zero ." << G4endl;
724  messageIn << " Inexact safety for volume " << motherPhysical->GetName() << G4endl
725  << " Solid: Name= " << motherSolid->GetName()
726  << " Type= " << motherSolid->GetEntityType() << G4endl;
727  messageIn << " Local point= " << localPoint << G4endl;
728  messageIn << " Solid parameters: " << G4endl << *motherSolid << G4endl;
729  G4Exception("G4VoxelNavigation::ComputeSafety()", "GeomNav0003",
730  JustWarning, messageIn);
731  }
732 #endif
733  // if( insideMother != kInside )
734  return 0.0;
735  }
736 
737 #ifdef G4VERBOSE
738  if( fCheck )
739  {
740  fLogger->ComputeSafetyLog (motherSolid,localPoint,motherSafety,true,true);
741  }
742 #endif
743  //
744  // Compute daughter safeties
745  //
746  // Look only inside the current Voxel only (in the first version).
747  //
748  curVoxelNode = fVoxelNode;
749  curNoVolumes = curVoxelNode->GetNoContained();
750 
751  for ( contentNo=curNoVolumes-1; contentNo>=0; contentNo-- )
752  {
753  sampleNo = curVoxelNode->GetVolume(contentNo);
754  samplePhysical = motherLogical->GetDaughter(sampleNo);
755 
756  G4AffineTransform sampleTf(samplePhysical->GetRotation(),
757  samplePhysical->GetTranslation());
758  sampleTf.Invert();
759  const G4ThreeVector samplePoint =
760  sampleTf.TransformPoint(localPoint);
761  const G4VSolid *sampleSolid =
762  samplePhysical->GetLogicalVolume()->GetSolid();
763  G4double sampleSafety = sampleSolid->DistanceToIn(samplePoint);
764  if ( sampleSafety<ourSafety )
765  {
766  ourSafety = sampleSafety;
767  }
768 #ifdef G4VERBOSE
769  if( fCheck )
770  {
771  fLogger->ComputeSafetyLog(sampleSolid,samplePoint,sampleSafety,false,false);
772  }
773 #endif
774  }
775  voxelSafety = ComputeVoxelSafety(localPoint);
776  if ( voxelSafety<ourSafety )
777  {
778  ourSafety = voxelSafety;
779  }
780  return ourSafety;
781 }
782 
783 // ********************************************************************
784 // SetVerboseLevel
785 // ********************************************************************
786 //
788 {
789  if( fLogger ) fLogger->SetVerboseLevel(level);
791 }
void SetVerboseLevel(G4int level)
void AlongComputeStepLog(const G4VSolid *sampleSolid, const G4ThreeVector &samplePoint, const G4ThreeVector &sampleDirection, const G4ThreeVector &localDirection, G4double sampleSafety, G4double sampleStep) const
G4String GetName() const
G4SmartVoxelHeader * GetHeader() const
G4VPhysicalVolume * GetTopVolume() const
G4int GetMinEquivalentSliceNo() const
void PrintDaughterLog(const G4VSolid *sampleSolid, const G4ThreeVector &samplePoint, G4double sampleSafety, G4bool onlySafety, const G4ThreeVector &sampleDirection, G4double sampleStep) const
const G4ThreeVector & GetTranslation() const
static const G4double kInfinity
Definition: geomdefs.hh:42
std::ostringstream G4ExceptionDescription
Definition: globals.hh:76
CLHEP::Hep3Vector G4ThreeVector
CLHEP::HepRotation G4RotationMatrix
G4int GetVolume(G4int pVolumeNo) const
G4double ComputeVoxelSafety(const G4ThreeVector &localPoint) const
G4double GetSurfaceTolerance() const
G4VPhysicalVolume * GetDaughter(const G4int i) const
G4double ComputeSafety(const G4ThreeVector &localPoint, const G4VPhysicalVolume &currentPhysical, G4double maxLength=DBL_MAX)
virtual G4GeometryType GetEntityType() const =0
std::vector< G4SmartVoxelHeader * > fVoxelHeaderStack
int G4int
Definition: G4Types.hh:78
std::vector< EAxis > fVoxelAxisStack
G4int GetNoContained() const
G4int GetMaxEquivalentSliceNo() const
void ReportOutsideMother(const G4ThreeVector &localPoint, const G4ThreeVector &localDirection, const G4VPhysicalVolume *motherPV, G4double tDist=30.0 *CLHEP::cm) const
G4bool IsNode() const
std::vector< G4double > fVoxelSliceWidthStack
G4AffineTransform & Invert()
EAxis GetAxis() const
G4BlockingList fBList
G4double GetMinExtent() const
const G4String & GetName() const
virtual EInside Inside(const G4ThreeVector &p) const =0
bool G4bool
Definition: G4Types.hh:79
G4bool LocateNextVoxel(const G4ThreeVector &localPoint, const G4ThreeVector &localDirection, const G4double currentStep)
std::vector< G4int > fVoxelNodeNoStack
void BlockVolume(const G4int v)
virtual G4double ComputeSafety(const G4ThreeVector &globalpoint, const G4NavigationHistory &history, const G4double pMaxLength=DBL_MAX)
G4bool IsBlocked(const G4int v) const
std::vector< G4int > fVoxelNoSlicesStack
G4bool CheckAndReportBadNormal(const G4ThreeVector &unitNormal, const G4ThreeVector &localPoint, const G4ThreeVector &localDirection, G4double step, const G4VSolid *solid, const char *msg) const
virtual G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const =0
static const double kMinExitingNormalCosine
Definition: geomdefs.hh:46
G4NavigationLogger * fLogger
G4int GetNoDaughters() const
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *comments)
Definition: G4Exception.cc:41
void SetVerboseLevel(G4int level)
G4ThreeVector TransformPoint(const G4ThreeVector &vec) const
virtual ~G4VoxelNavigation()
G4LogicalVolume * GetLogicalVolume() const
G4SmartVoxelNode * GetNode() const
EInside
Definition: geomdefs.hh:58
void ComputeSafetyLog(const G4VSolid *solid, const G4ThreeVector &point, G4double safety, G4bool isMotherVolume, G4int banner=-1) const
EAxis
Definition: geomdefs.hh:54
void SetVerboseLevel(G4int level)
void PreComputeStepLog(const G4VPhysicalVolume *motherPhysical, G4double motherSafety, const G4ThreeVector &localPoint) const
virtual G4int GetCopyNo() const =0
const G4RotationMatrix * GetRotation() const
T min(const T t1, const T t2)
brief Return the smallest of the two arguments
G4VoxelSafety * fpVoxelSafety
static const G4int kNavigatorVoxelStackMax
Definition: geomdefs.hh:80
G4SmartVoxelNode * fVoxelNode
#define G4endl
Definition: G4ios.hh:61
void PostComputeStepLog(const G4VSolid *motherSolid, const G4ThreeVector &localPoint, const G4ThreeVector &localDirection, G4double motherStep, G4double motherSafety) const
void CheckDaughterEntryPoint(const G4VSolid *sampleSolid, const G4ThreeVector &samplePoint, const G4ThreeVector &sampleDirection, const G4VSolid *motherSolid, const G4ThreeVector &localPoint, const G4ThreeVector &localDirection, G4double motherStep, G4double sampleStep) const
double G4double
Definition: G4Types.hh:76
virtual G4double DistanceToOut(const G4ThreeVector &p, const G4ThreeVector &v, const G4bool calcNorm=false, G4bool *validNorm=0, G4ThreeVector *n=0) const =0
virtual G4double ComputeStep(const G4ThreeVector &globalPoint, const G4ThreeVector &globalDirection, const G4double currentProposedStepLength, G4double &newSafety, G4NavigationHistory &history, G4bool &validExitNormal, G4ThreeVector &exitNormal, G4bool &exiting, G4bool &entering, G4VPhysicalVolume *(*pBlockedPhysical), G4int &blockedReplicaNo)
#define DBL_MAX
Definition: templates.hh:83
static G4GeometryTolerance * GetInstance()
G4VSolid * GetSolid() const
void Enlarge(const G4int nv)