source: trunk/source/geometry/navigation/src/G4VoxelSafety.cc@ 1350

Last change on this file since 1350 was 1350, checked in by garnier, 15 years ago

update to last version 4.9.4

File size: 12.7 KB
Line 
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: G4VoxelSafety.cc,v 1.9 2010/11/11 16:15:00 gcosmo Exp $
28// GEANT4 tag $Name: geant4-09-04-ref-00 $
29//
30// Author: John Apostolakis
31// First version: 31 May 2010
32//
33#include "G4VoxelSafety.hh"
34
35#include "G4GeometryTolerance.hh"
36
37#include "G4SmartVoxelProxy.hh"
38#include "G4SmartVoxelNode.hh"
39#include "G4SmartVoxelHeader.hh"
40
41// State
42// - values used during computation of Safety
43//
44// Constructor
45// - copied from G4VoxelNavigation (1st version)
46G4VoxelSafety::G4VoxelSafety()
47 : fBlockList(),
48 fpMotherLogical(0),
49 fVoxelDepth(-1),
50 fVoxelAxisStack(kNavigatorVoxelStackMax,kXAxis),
51 fVoxelNoSlicesStack(kNavigatorVoxelStackMax,0),
52 fVoxelSliceWidthStack(kNavigatorVoxelStackMax,0.),
53 fVoxelNodeNoStack(kNavigatorVoxelStackMax,0),
54 fVoxelHeaderStack(kNavigatorVoxelStackMax,(G4SmartVoxelHeader*)0),
55 fVoxelNode(0),
56 fCheck(false),
57 fVerbose(0)
58{
59 kCarTolerance = G4GeometryTolerance::GetInstance()->GetSurfaceTolerance();
60}
61
62G4VoxelSafety::~G4VoxelSafety()
63{
64}
65
66// ********************************************************************
67// ComputeSafety
68//
69// Calculates the isotropic distance to the nearest boundary from the
70// specified point in the local coordinate system.
71// The localpoint utilised must be within the current volume.
72// ********************************************************************
73//
74G4double
75G4VoxelSafety::ComputeSafety(const G4ThreeVector& localPoint,
76 const G4VPhysicalVolume& currentPhysical,
77 G4double ) // maxLength)
78{
79 // G4VPhysicalVolume *samplePhysical;
80 G4LogicalVolume *motherLogical;
81 G4VSolid *motherSolid;
82 G4SmartVoxelHeader *motherVoxelHeader;
83 G4double motherSafety, ourSafety;
84 G4int localNoDaughters; // , sampleNo;
85 // G4SmartVoxelNode *curVoxelNode;
86 // G4int curNoVolumes, contentNo;
87 G4double daughterSafety;
88
89 motherLogical = currentPhysical.GetLogicalVolume();
90 fpMotherLogical= motherLogical; // For use by the other methods
91 motherSolid = motherLogical->GetSolid();
92 motherVoxelHeader= motherLogical->GetVoxelHeader();
93
94#ifdef G4VERBOSE
95 if( fVerbose > 0 ){
96 G4cout << "*** G4VoxelSafety::ComputeSafety(): ***" << G4endl;
97 }
98#endif
99
100 // Check that point is inside mother volume
101 EInside insideMother= motherSolid->Inside(localPoint);
102 if( insideMother != kInside ) {
103 if( insideMother == kOutside ) {
104 G4cerr << " G4VoxelSafety> Location for safety is Outside current volume. " << G4endl;
105 G4cerr << " The approximate distance to the solid (safety from outside ) is "
106 << motherSolid->DistanceToIn( localPoint ) << G4endl;
107 G4Exception("G4VoxelSafety::ComputeSafety()",
108 "IllegalLocationForSafetyCall", FatalException,
109 "Method called for location outside current Volume.");
110 }
111 return 0.0;
112 }
113
114 // First limit: mother safety - distance to outer boundaries
115 motherSafety = motherSolid->DistanceToOut(localPoint);
116 ourSafety = motherSafety; // Working isotropic safety
117
118#ifdef G4VERBOSE
119 if(( fCheck ) && ( fVerbose == 1 ))
120 {
121 G4cout << "*** G4VoxelSafety::ComputeSafety(): ***" << G4endl
122 << " Invoked DistanceToOut(p) for mother solid: "
123 << motherSolid->GetName()
124 << ". Solid replied: " << motherSafety << G4endl
125 << " For local point p: " << localPoint
126 << ", to be considered as 'mother safety'." << G4endl;
127 }
128#endif
129 localNoDaughters = motherLogical->GetNoDaughters();
130
131 fBlockList.Enlarge(localNoDaughters);
132 fBlockList.Reset();
133
134 fVoxelDepth = -1; // Resets the depth -- must be done for next method
135 daughterSafety= SafetyForVoxelHeader( motherVoxelHeader, localPoint );
136
137 ourSafety= std::min( motherSafety, daughterSafety );
138
139 return ourSafety;
140}
141
142// Calculate the safety for volumes included in current Voxel Node
143//
144G4double
145G4VoxelSafety::
146SafetyForVoxelNode( G4SmartVoxelNode *curVoxelNode,
147 const G4ThreeVector& localPoint )
148{
149 G4double ourSafety= DBL_MAX;
150
151 G4int curNoVolumes, contentNo, sampleNo;
152 G4VPhysicalVolume *samplePhysical;
153
154 G4double sampleSafety=0.0;
155 G4ThreeVector samplePoint;
156 G4VSolid* ptrSolid=0;
157
158 curNoVolumes = curVoxelNode->GetNoContained();
159
160 for ( contentNo=curNoVolumes-1; contentNo>=0; contentNo-- )
161 {
162 sampleNo = curVoxelNode->GetVolume(contentNo);
163 if ( !fBlockList.IsBlocked(sampleNo) )
164 {
165 fBlockList.BlockVolume(sampleNo);
166
167 samplePhysical = fpMotherLogical->GetDaughter(sampleNo);
168 G4AffineTransform sampleTf(samplePhysical->GetRotation(),
169 samplePhysical->GetTranslation());
170 sampleTf.Invert();
171 samplePoint = sampleTf.TransformPoint(localPoint);
172 ptrSolid = samplePhysical->GetLogicalVolume()->GetSolid();
173
174 sampleSafety = ptrSolid->DistanceToIn(samplePoint);
175 ourSafety = std::min( sampleSafety, ourSafety );
176#ifdef G4VERBOSE
177 if(( fCheck ) && ( fVerbose == 1 ))
178 {
179 // ReportSolidSafetyToIn( MethodName, solid, value, point );
180 G4cout << "*** G4VoxelSafety::SafetyForVoxelNode(): ***" << G4endl
181 << " Invoked DistanceToIn(p) for daughter solid: "
182 << ptrSolid->GetName()
183 << ". Solid replied: " << sampleSafety << G4endl
184 << " For local point p: " << samplePoint
185 << ", to be considered as 'daughter safety'." << G4endl;
186 }
187#endif
188 }
189 } // end for contentNo
190
191 return ourSafety;
192}
193
194
195//
196// Pseudo-code for Compute Safety
197//
198// for each (potential) dimension of depth
199// iterate through VoxelProxies (Header, Node)
200// until distanceToVoxel > estimatedSafety
201//
202// Better:
203// iterate through/down the three of VoxelProxies
204// while distanceToVoxel <= estimatedSafety
205// Examine one Nodes for which this condition holds.
206// (version 0 can examine all nodes)
207
208
209// How to step through voxels ?? Thu 29 April 2010 @ 17:00
210
211// ********************************************************************
212// SafetyForVoxelHeader method
213// - which cycles through levels of headers to process each node level
214// - Obtained by modifying VoxelLocate (to cycle through Node Headers)
215// *********************************************************************
216//
217G4double
218G4VoxelSafety::SafetyForVoxelHeader( G4SmartVoxelHeader* pHeader,
219 const G4ThreeVector& localPoint )
220{
221 const G4SmartVoxelHeader *targetVoxelHeader=pHeader;
222 G4SmartVoxelNode *targetVoxelNode=0;
223
224 G4SmartVoxelProxy *sampleProxy;
225 EAxis targetHeaderAxis;
226 G4double targetHeaderMin, targetHeaderNodeWidth;
227 G4int targetHeaderNoSlices;
228 G4int targetNodeNo; // , pointNodeNo;
229 // G4int minCurNodeNoDelta, maxCurNodeNoDelta;
230
231 G4double minSafety= DBL_MAX;
232
233 fVoxelDepth++;
234 // fVoxelDepth set by ComputeSafety or previous level call
235
236 targetHeaderAxis = targetVoxelHeader->GetAxis();
237 targetHeaderNoSlices = targetVoxelHeader->GetNoSlices();
238 targetHeaderMin = targetVoxelHeader->GetMinExtent();
239 targetHeaderNodeWidth = (targetVoxelHeader->GetMaxExtent()-targetHeaderMin)
240 / targetHeaderNoSlices;
241
242 const G4int pointNodeNo = G4int( (localPoint(targetHeaderAxis)-targetHeaderMin)
243 / targetHeaderNodeWidth);
244 // Ensure that it is between 0 and targetHeader->GetMaxExtent() - 1
245
246 G4cout << " Calculated pointNodeNo= " << pointNodeNo
247 << " from position= " << localPoint(targetHeaderAxis)
248 << " min= " << targetHeaderMin
249 << " max= " << targetVoxelHeader->GetMaxExtent()
250 << " width= " << targetHeaderNodeWidth
251 << " no-slices= " << targetHeaderNoSlices
252 << " axis= " << targetHeaderAxis
253 << G4endl;
254
255 // Stack info for stepping
256 //
257 fVoxelAxisStack[fVoxelDepth] = targetHeaderAxis;
258 fVoxelNoSlicesStack[fVoxelDepth] = targetHeaderNoSlices;
259 fVoxelSliceWidthStack[fVoxelDepth] = targetHeaderNodeWidth;
260
261
262 fVoxelHeaderStack[fVoxelDepth] = pHeader;
263
264#ifdef G4VERBOSE
265 if( fVerbose > 2 ){
266 G4cout << G4endl;
267 G4cout << "**** G4VoxelSafety::SafetyForVoxelHeader " << G4endl;
268 G4cout << " Depth = " << fVoxelDepth ; // << G4endl;
269 G4cout << " Number of Slices = " << targetHeaderNoSlices ; // << G4endl;
270 G4cout << " Header (address) = " << targetVoxelHeader << G4endl;
271 }
272#endif
273 // G4int numSlicesCheck= targetHeaderNoSlices;
274
275 // G4cout << "---> Current Voxel Header has " << *targetVoxelHeader << G4endl;
276
277 // targetVoxelHeader->GetMaxEquivalentSliceNo()+1;
278 // targetVoxelHeader->GetMinEquivalentSliceNo()-1;
279
280 G4int nextUp= pointNodeNo+1;
281 G4int nextDown= pointNodeNo-1;
282 // Ignore equivalents for now
283 G4int nextNode= pointNodeNo;
284
285 for( targetNodeNo= pointNodeNo;
286 // (targetNodeNo<targetHeaderNoSlices) &&
287 (targetNodeNo>=0);
288 targetNodeNo= nextNode
289 )
290 {
291 G4double nodeSafety= DBL_MAX, levelSafety= DBL_MAX;
292 fVoxelNodeNoStack[fVoxelDepth] = targetNodeNo;
293
294 sampleProxy = targetVoxelHeader->GetSlice(targetNodeNo);
295
296 G4cout << " -Checking node " << targetNodeNo
297 << " is proxy with address " << sampleProxy; // << G4endl;
298
299 if ( sampleProxy->IsNode() )
300 {
301 targetVoxelNode = sampleProxy->GetNode();
302 G4cout << " -- It is a Node " << G4endl;
303
304 // Deal with the node here [ i.e. the last level ]
305 nodeSafety= SafetyForVoxelNode( targetVoxelNode, localPoint);
306 // if( targetHeaderNoSlices != numSlicesCheck )
307 // G4cerr << "Number of slices changed - to " << targetHeaderNoSlices << G4endl;
308 minSafety= std::min( minSafety, nodeSafety );
309 }
310 else
311 {
312 G4SmartVoxelHeader *pNewVoxelHeader = sampleProxy->GetHeader();
313 // fVoxelDepth++;
314
315 G4cout << " -- It is a Header " << G4endl;
316 G4cout << " Recurse to deal with next level, fVoxelDepth= "
317 << fVoxelDepth+1 << G4endl;
318
319 // Recurse to deal with lower levels
320 levelSafety= SafetyForVoxelHeader( pNewVoxelHeader, localPoint);
321 // fVoxelDepth--;
322
323 // G4cout << " Returned from SafetyForVoxelHeader. Depth= "
324 // << fVoxelDepth << G4endl;
325 //--G4cout << " Decreased fVoxelDepth to " << fVoxelDepth << G4endl;
326 //--G4cout << " Header (address)= " << targetVoxelHeader << G4endl;
327 G4cout << " Level safety = " << levelSafety << G4endl;
328
329 minSafety= std::min( minSafety, levelSafety );
330 }
331
332 // Find next closest Voxel
333 // - first try: by simple subtraction
334 // - later: using distance (TODO - tbc)
335 G4cout << " Next: up " << nextUp << " d= " << nextUp - pointNodeNo
336 << " down " << nextDown << " d= " << pointNodeNo - nextDown
337 << " cond " << ( nextUp < targetHeaderNoSlices )
338 << " pointNodeNo= " << pointNodeNo
339 << G4endl;
340 if( ((nextUp - pointNodeNo) < (pointNodeNo - nextDown))
341 && (nextUp < targetHeaderNoSlices) )
342 {
343 nextNode=nextUp;
344 ++nextUp;
345 G4cout << " Chose Up: next= " << nextNode << " new= " << nextUp << G4endl;
346 }else{
347 nextNode=nextDown;
348 --nextDown;
349 G4cout << " Chose Down: next= " << nextNode << " new= " << nextDown << G4endl;
350 }
351 }
352
353#ifdef G4VERBOSE
354 if( fVerbose > 0 ) {
355 G4cout << " Ended for targetNodeNo -- checked "
356 << targetHeaderNoSlices << " slices" << G4endl;
357 G4cout << " ===== Returning from SafetyForVoxelHeader "
358 << " Depth= " << fVoxelDepth << G4endl
359 << G4endl;
360 }
361#endif
362
363 // Go back one level
364 fVoxelDepth--;
365
366 return minSafety;
367}
Note: See TracBrowser for help on using the repository browser.