Geant4 9.6.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4GeomTestSegment.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$
28//
29// --------------------------------------------------------------------
30// GEANT 4 class source file
31//
32// G4GeomTestSegment
33//
34// Author: D.C.Williams, UCSC ([email protected])
35// --------------------------------------------------------------------
36
37#include "G4GeomTestSegment.hh"
38
39#include "G4VSolid.hh"
40#include "G4GeomTestLogger.hh"
42
43//
44// Constructor
45//
47 const G4ThreeVector &theP,
48 const G4ThreeVector &theV,
49 G4GeomTestLogger *logger )
50 : solid(theSolid),
51 p0(theP),
52 v(theV)
53{
55 FindPoints(logger);
56}
57
58
59//
60// Simple accessors
61//
62const G4VSolid * G4GeomTestSegment::GetSolid() const { return solid; }
63
64const G4ThreeVector &G4GeomTestSegment::GetP() const { return p0; }
65
66const G4ThreeVector &G4GeomTestSegment::GetV() const { return v; }
67
68
69//
70// Return number points
71//
73{
74 return points.size();
75}
76
77
78//
79// Return ith point
80//
82{
83 return points[i];
84}
85
86
87//
88// FindPoints
89//
90// Do the dirty work
91//
92void G4GeomTestSegment::FindPoints( G4GeomTestLogger *logger )
93{
94 FindSomePoints( logger, true );
95 FindSomePoints( logger, false );
96
97 PatchInconsistencies( logger );
98}
99
100
101//
102// PatchInconsistencies
103//
104// Search for inconsistancies in the hit list and patch
105// them up, if possible
106//
107void G4GeomTestSegment::PatchInconsistencies( G4GeomTestLogger *logger )
108{
109 if (points.size() == 0) return;
110
111 //
112 // Sort
113 //
114 std::sort( points.begin(), points.end() );
115
116 //
117 // Loop over entering/leaving pairs
118 //
119 std::vector<G4GeomTestPoint>::iterator curr = points.begin();
120 do {
121
122 std::vector<G4GeomTestPoint>::iterator next = curr + 1;
123
124 //
125 // Is the next point close by?
126 //
127 while (next != points.end() &&
128 next->GetDistance()-curr->GetDistance() < kCarTolerance) {
129 //
130 // Yup. If we have an entering/leaving pair, all is okay
131 //
132 if (next->Entering() != curr->Entering()) {
133 curr = next + 1;
134 next = curr + 1;
135
136 break;
137 }
138
139 //
140 // Otherwise, they are duplicate, and just delete one
141 //
142 next = points.erase(next);
143 curr = next - 1;
144
145 }
146
147 if (curr == points.end()) break;
148
149 //
150 // The next point should be entering...
151 //
152
153 if (!curr->Entering()) {
154 //
155 // Point is out of sequence:
156 // Test solid just before this point
157 //
158 G4double ds = curr->GetDistance();
159 G4ThreeVector p = p0 + ds*v;
160
161 G4ThreeVector p1 = p - 10*kCarTolerance*v;
162
163 if (solid->Inside(p1) == kOutside||(solid->Inside(p1)== kSurface)) {
164 //
165 // We are missing an entrance point near the current
166 // point. Add one.
167 //
168 curr = points.insert(curr, G4GeomTestPoint( p, ds, true ) );
169 ++curr;
170 break;
171 }
172
173 //
174 // Test solid just after last point
175 //
176 if (curr != points.begin()) {
177 std::vector<G4GeomTestPoint>::iterator prev = curr - 1;
178
179 ds = prev->GetDistance();
180 p = p0 + ds*v;
181
182 p1 = p + 10*kCarTolerance*v;
183 if ((solid->Inside(p1) == kOutside)||(solid->Inside(p1)== kSurface)) {
184
185 //
186 // We are missing an entrance point near the previous
187 // point. Add one.
188 //
189 curr = points.insert(curr, G4GeomTestPoint( p, ds, true ) );
190 ++curr;
191 break;
192 }
193 }
194
195 //
196 // Oh oh. No solution. Delete the current point and complain.
197 //
198 logger->SolidProblem( solid, "Spurious exiting intersection point", p );
199 curr = points.erase(curr);
200 break;
201 }
202
203 //
204 // The following point should be leaving
205 //
206
207 if (next == points.end() || next->Entering() ) {
208 //
209 // But is missing. Check immediately after this point.
210 //
211 G4double ds = curr->GetDistance();
212 G4ThreeVector p = p0 + ds*v;
213 G4ThreeVector p1 = p + 10*kCarTolerance*v;
214
215 if (solid->Inside(p1) == kOutside) {
216 //
217 // We are missing an exit point near the current
218 // point. Add one.
219 //
220 curr = points.insert(next, G4GeomTestPoint( p, ds, false ) );
221 break;
222 }
223
224 if (next != points.end()) {
225 //
226 // Check just before next point
227 //
228 ds = next->GetDistance();
229 p = p0 + ds*v;
230 p1 = p - 10*kCarTolerance*v;
231 if (solid->Inside(p1) == kOutside) {
232 //
233 // We are missing an exit point before the next
234 // point. Add one.
235 //
236 curr = points.insert(next, G4GeomTestPoint( p, ds, false ) );
237 break;
238 }
239 }
240
241 //
242 // Oh oh. Hanging entering point. Delete and complain.
243 //
244 logger->SolidProblem( solid, "Spurious entering intersection point", p );
245 curr = points.erase(curr);
246 }
247
248 if(curr!=points.end()){curr = next + 1;}
249
250 } while( curr != points.end() );
251
252 //
253 // Double check
254 //
255 if (points.size()&1)
256 logger->SolidProblem( solid,
257 "Solid has odd number of intersection points", p0 );
258
259 return;
260}
261
262
263//
264// Find intersections either in front or behind the point
265//
266void G4GeomTestSegment::FindSomePoints( G4GeomTestLogger *logger,
267 G4bool forward )
268{
269 G4double sign = forward ? +1 : -1;
270
271 G4ThreeVector p(p0);
272 G4ThreeVector vSearch(sign*v);
273 G4double ds(0);
274 G4bool entering;
275 G4double vSurfN;
276
277 // Look for nearest intersection point in the specified
278 // direction and return if there isn't one
279 //
280 G4double dist;
281 switch(solid->Inside(p)) {
282 case kInside:
283 dist = solid->DistanceToOut(p,vSearch);
284 if (dist >= kInfinity) {
285 logger->SolidProblem( solid,
286 "DistanceToOut(p,v) = kInfinity for point inside", p );
287 return;
288 }
289 ds += sign*dist;
290 entering = false;
291 break;
292 case kOutside:
293 dist = solid->DistanceToIn(p,vSearch);
294 if (dist >= kInfinity) return;
295 ds += sign*dist;
296 entering = true;
297 break;
298 case kSurface:
299 vSurfN=v.dot(solid->SurfaceNormal(p));
300 if(std::fabs(vSurfN)<kCarTolerance)vSurfN=0;
301 entering = (vSurfN < 0);
302 break;
303 default:
304 logger->SolidProblem( solid,
305 "Inside returns illegal enumerated value", p );
306 return;
307 }
308
309 //
310 // Loop
311 //
312 // nzero = the number of consecutive zeros
313 //
314 G4int nzero=0;
315
316 for(;;) {
317 //
318 // Locate point
319 //
320 p = p0 + ds*v;
321
322 if (nzero > 2) {
323 //
324 // Oops. In a loop. Probably along a spherical or cylindrical surface.
325 // Let's give the tool a little help with a push
326 //
327 G4double push = 1E-6;
328 ds += sign*push;
329 for(;;) {
330 p = p0 + ds*v;
331 EInside inside = solid->Inside(p);
332 if (inside == kInside) {
333 entering = true;
334 break;
335 }
336 else if (inside == kOutside) {
337 entering = false;
338 break;
339 }
340
341 push = 2*push;
342 if (push > 0.1) {
343 logger->SolidProblem( solid,
344 "Push fails to fix geometry inconsistency", p );
345 return;
346 }
347 ds += sign*push;
348 }
349 }
350 else {
351
352 //
353 // Record point
354 //
355 points.push_back( G4GeomTestPoint( p, ds, entering==forward ) );
356
357 }
358
359 //
360 // Find next intersection
361 //
362 if (entering) {
363 dist = solid->DistanceToOut(p,vSearch);
364 if (dist >= kInfinity) {
365 logger->SolidProblem( solid,
366 "DistanceToOut(p,v) = kInfinity for point inside", p );
367 return;
368 }
369
370 if ( (dist > kCarTolerance)
371 && (solid->Inside(p + (dist*0.999)*vSearch) == kOutside) ) {
372 //
373 // This shouldn't have happened
374 //
375 if (solid->Inside(p) == kOutside)
376 logger->SolidProblem(solid,
377 "Entering point is outside (possible roundoff error)",p);
378 else
379 logger->SolidProblem(solid,
380 "DistanceToOut(p,v) brings trajectory well outside solid",p);
381 return;
382 }
383
384 entering = false;
385 }
386 else {
387 dist = solid->DistanceToIn(p,vSearch);
388 if (dist >= kInfinity) return;
389
390 if ( (dist > kCarTolerance)
391 && (solid->Inside(p + (dist*0.999)*vSearch) == kInside) ) {
392 //
393 // This shouldn't have happened
394 //
395 if (solid->Inside(p) == kInside)
396 logger->SolidProblem(solid,
397 "Exiting point is inside (possible roundoff error)", p);
398 else
399 logger->SolidProblem(solid,
400 "DistanceToIn(p,v) brings trajectory well inside solid", p);
401 return;
402 }
403
404 entering = true;
405 }
406
407 //
408 // Update ds
409 //
410 if (dist <= 0) {
411 nzero++;
412 }
413 else {
414 nzero=0;
415 ds += sign*dist;
416 }
417 }
418}
double G4double
Definition: G4Types.hh:64
int G4int
Definition: G4Types.hh:66
bool G4bool
Definition: G4Types.hh:67
virtual void SolidProblem(const G4VSolid *solid, const G4String &message, const G4ThreeVector &point)=0
G4int GetNumberPoints() const
const G4ThreeVector & GetV() const
const G4VSolid * GetSolid() const
const G4ThreeVector & GetP() const
G4GeomTestSegment(const G4VSolid *theSolid, const G4ThreeVector &theP, const G4ThreeVector &theV, G4GeomTestLogger *logger)
const G4GeomTestPoint & GetPoint(G4int i) const
G4double GetSurfaceTolerance() const
static G4GeometryTolerance * GetInstance()
virtual EInside Inside(const G4ThreeVector &p) const =0
virtual G4double DistanceToOut(const G4ThreeVector &p, const G4ThreeVector &v, const G4bool calcNorm=false, G4bool *validNorm=0, G4ThreeVector *n=0) const =0
virtual G4ThreeVector SurfaceNormal(const G4ThreeVector &p) const =0
virtual G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const =0
EInside
Definition: geomdefs.hh:58
@ kInside
Definition: geomdefs.hh:58
@ kOutside
Definition: geomdefs.hh:58
@ kSurface
Definition: geomdefs.hh:58
G4int sign(T t)