Geant4 9.6.0
Toolkit for the simulation of the passage of particles through matter
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
G4ClippablePolygon.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// --------------------------------------------------------------------
31// GEANT 4 class source file
32//
33//
34// G4ClippablePolygon.cc
35//
36// Includes code from G4VSolid (P.Kent, V.Grichine, J.Allison)
37//
38// --------------------------------------------------------------------
39
40#include "G4ClippablePolygon.hh"
41
42#include "G4VoxelLimits.hh"
44
45//
46// Constructor
47//
49 : normal(0.,0.,0.)
50{
52}
53
54
55//
56// Destructor
57//
59{
60}
61
62
63//
64// AddVertexInOrder
65//
67{
68 vertices.push_back( vertex );
69}
70
71
72//
73// ClearAllVertices
74//
76{
77 vertices.clear();
78}
79
80
81//
82// Clip
83//
85{
86 if (voxelLimit.IsLimited()) {
87 ClipAlongOneAxis( voxelLimit, kXAxis );
88 ClipAlongOneAxis( voxelLimit, kYAxis );
89 ClipAlongOneAxis( voxelLimit, kZAxis );
90 }
91
92 return (vertices.size() > 0);
93}
94
95
96//
97// PartialClip
98//
99// Clip, while ignoring the indicated axis
100//
102 const EAxis IgnoreMe )
103{
104 if (voxelLimit.IsLimited()) {
105 if (IgnoreMe != kXAxis) ClipAlongOneAxis( voxelLimit, kXAxis );
106 if (IgnoreMe != kYAxis) ClipAlongOneAxis( voxelLimit, kYAxis );
107 if (IgnoreMe != kZAxis) ClipAlongOneAxis( voxelLimit, kZAxis );
108 }
109
110 return (vertices.size() > 0);
111}
112
113
114//
115// GetExtent
116//
118 G4double &min,
119 G4double &max ) const
120{
121 //
122 // Okay, how many entries do we have?
123 //
124 G4int noLeft = vertices.size();
125
126 //
127 // Return false if nothing is left
128 //
129 if (noLeft == 0) return false;
130
131 //
132 // Initialize min and max to our first vertex
133 //
134 min = max = vertices[0].operator()( axis );
135
136 //
137 // Compare to the rest
138 //
139 G4int i;
140 for( i=1; i<noLeft; i++ )
141 {
142 G4double component = vertices[i].operator()( axis );
143 if (component < min )
144 min = component;
145 else if (component > max )
146 max = component;
147 }
148
149 return true;
150}
151
152
153//
154// GetMinPoint
155//
156// Returns pointer to minimum point along the specified axis.
157// Take care! Do not use pointer after destroying parent polygon.
158//
160{
161 G4int noLeft = vertices.size();
162 if (noLeft==0)
163 G4Exception("G4ClippablePolygon::GetMinPoint()",
164 "GeomSolids0002", FatalException, "Empty polygon.");
165
166 const G4ThreeVector *answer = &(vertices[0]);
167 G4double min = answer->operator()(axis);
168
169 G4int i;
170 for( i=1; i<noLeft; i++ )
171 {
172 G4double component = vertices[i].operator()( axis );
173 if (component < min)
174 {
175 answer = &(vertices[i]);
176 min = component;
177 }
178 }
179
180 return answer;
181}
182
183
184//
185// GetMaxPoint
186//
187// Returns pointer to maximum point along the specified axis.
188// Take care! Do not use pointer after destroying parent polygon.
189//
191{
192 G4int noLeft = vertices.size();
193 if (noLeft==0)
194 G4Exception("G4ClippablePolygon::GetMaxPoint()",
195 "GeomSolids0002", FatalException, "Empty polygon.");
196
197 const G4ThreeVector *answer = &(vertices[0]);
198 G4double max = answer->operator()(axis);
199
200 G4int i;
201 for( i=1; i<noLeft; i++ )
202 {
203 G4double component = vertices[i].operator()( axis );
204 if (component > max)
205 {
206 answer = &(vertices[i]);
207 max = component;
208 }
209 }
210
211 return answer;
212}
213
214
215//
216// InFrontOf
217//
218// Decide if this polygon is in "front" of another when
219// viewed along the specified axis. For our purposes here,
220// it is sufficient to use the minimum extent of the
221// polygon along the axis to determine this.
222//
223// In case the minima of the two polygons are equal,
224// we use a more sophisticated test.
225//
226// Note that it is possible for the two following
227// statements to both return true or both return false:
228// polygon1.InFrontOf(polygon2)
229// polygon2.BehindOf(polygon1)
230//
232 EAxis axis ) const
233{
234 //
235 // If things are empty, do something semi-sensible
236 //
237 G4int noLeft = vertices.size();
238 if (noLeft==0) return false;
239
240 if (other.Empty()) return true;
241
242 //
243 // Get minimum of other polygon
244 //
245 const G4ThreeVector *minPointOther = other.GetMinPoint( axis );
246 const G4double minOther = minPointOther->operator()(axis);
247
248 //
249 // Get minimum of this polygon
250 //
251 const G4ThreeVector *minPoint = GetMinPoint( axis );
252 const G4double min = minPoint->operator()(axis);
253
254 //
255 // Easy decision
256 //
257 if (min < minOther-kCarTolerance) return true; // Clear winner
258
259 if (minOther < min-kCarTolerance) return false; // Clear loser
260
261 //
262 // We have a tie (this will not be all that rare since our
263 // polygons are connected)
264 //
265 // Check to see if there is a vertex in the other polygon
266 // that is behind this one (or vice versa)
267 //
268 G4bool answer;
269 G4ThreeVector normalOther = other.GetNormal();
270
271 if (std::fabs(normalOther(axis)) > std::fabs(normal(axis)))
272 {
273 G4double minP, maxP;
274 GetPlanerExtent( *minPointOther, normalOther, minP, maxP );
275
276 answer = (normalOther(axis) > 0) ? (minP < -kCarTolerance)
277 : (maxP > +kCarTolerance);
278 }
279 else
280 {
281 G4double minP, maxP;
282 other.GetPlanerExtent( *minPoint, normal, minP, maxP );
283
284 answer = (normal(axis) > 0) ? (maxP > +kCarTolerance)
285 : (minP < -kCarTolerance);
286 }
287 return answer;
288}
289
290//
291// BehindOf
292//
293// Decide if this polygon is behind another.
294// See notes in method "InFrontOf"
295//
297 EAxis axis ) const
298{
299 //
300 // If things are empty, do something semi-sensible
301 //
302 G4int noLeft = vertices.size();
303 if (noLeft==0) return false;
304
305 if (other.Empty()) return true;
306
307 //
308 // Get minimum of other polygon
309 //
310 const G4ThreeVector *maxPointOther = other.GetMaxPoint( axis );
311 const G4double maxOther = maxPointOther->operator()(axis);
312
313 //
314 // Get minimum of this polygon
315 //
316 const G4ThreeVector *maxPoint = GetMaxPoint( axis );
317 const G4double max = maxPoint->operator()(axis);
318
319 //
320 // Easy decision
321 //
322 if (max > maxOther+kCarTolerance) return true; // Clear winner
323
324 if (maxOther > max+kCarTolerance) return false; // Clear loser
325
326 //
327 // We have a tie (this will not be all that rare since our
328 // polygons are connected)
329 //
330 // Check to see if there is a vertex in the other polygon
331 // that is in front of this one (or vice versa)
332 //
333 G4bool answer;
334 G4ThreeVector normalOther = other.GetNormal();
335
336 if (std::fabs(normalOther(axis)) > std::fabs(normal(axis)))
337 {
338 G4double minP, maxP;
339 GetPlanerExtent( *maxPointOther, normalOther, minP, maxP );
340
341 answer = (normalOther(axis) > 0) ? (maxP > +kCarTolerance)
342 : (minP < -kCarTolerance);
343 }
344 else
345 {
346 G4double minP, maxP;
347 other.GetPlanerExtent( *maxPoint, normal, minP, maxP );
348
349 answer = (normal(axis) > 0) ? (minP < -kCarTolerance)
350 : (maxP > +kCarTolerance);
351 }
352 return answer;
353}
354
355
356//
357// GetPlanerExtent
358//
359// Get min/max distance in or out of a plane
360//
362 const G4ThreeVector &planeNormal,
363 G4double &min,
364 G4double &max ) const
365{
366 //
367 // Okay, how many entries do we have?
368 //
369 G4int noLeft = vertices.size();
370
371 //
372 // Return false if nothing is left
373 //
374 if (noLeft == 0) return false;
375
376 //
377 // Initialize min and max to our first vertex
378 //
379 min = max = planeNormal.dot(vertices[0]-pointOnPlane);
380
381 //
382 // Compare to the rest
383 //
384 G4int i;
385 for( i=1; i<noLeft; i++ )
386 {
387 G4double component = planeNormal.dot(vertices[i] - pointOnPlane);
388 if (component < min )
389 min = component;
390 else if (component > max )
391 max = component;
392 }
393
394 return true;
395}
396
397
398//
399// Clip along just one axis, as specified in voxelLimit
400//
402 const EAxis axis )
403{
404 if (!voxelLimit.IsLimited(axis)) return;
405
406 G4ThreeVectorList tempPolygon;
407
408 //
409 // Build a "simple" voxelLimit that includes only the min extent
410 // and apply this to our vertices, producing result in tempPolygon
411 //
412 G4VoxelLimits simpleLimit1;
413 simpleLimit1.AddLimit( axis, voxelLimit.GetMinExtent(axis), kInfinity );
414 ClipToSimpleLimits( vertices, tempPolygon, simpleLimit1 );
415
416 //
417 // If nothing is left from the above clip, we might as well return now
418 // (but with an empty vertices)
419 //
420 if (tempPolygon.size() == 0)
421 {
422 vertices.clear();
423 return;
424 }
425
426 //
427 // Now do the same, but using a "simple" limit that includes only the max
428 // extent. Apply this to out tempPolygon, producing result in vertices.
429 //
430 G4VoxelLimits simpleLimit2;
431 simpleLimit2.AddLimit( axis, -kInfinity, voxelLimit.GetMaxExtent(axis) );
432 ClipToSimpleLimits( tempPolygon, vertices, simpleLimit2 );
433
434 //
435 // If nothing is left, return now
436 //
437 if (vertices.size() == 0) return;
438}
439
440
441//
442// pVoxelLimits must be only limited along one axis, and either the maximum
443// along the axis must be +kInfinity, or the minimum -kInfinity
444//
445void G4ClippablePolygon::ClipToSimpleLimits( G4ThreeVectorList& pPolygon,
446 G4ThreeVectorList& outputPolygon,
447 const G4VoxelLimits& pVoxelLimit )
448{
449 G4int i;
450 G4int noVertices=pPolygon.size();
451 G4ThreeVector vEnd,vStart;
452
453 outputPolygon.clear();
454
455 for (i=0;i<noVertices;i++)
456 {
457 vStart=pPolygon[i];
458 if (i==noVertices-1)
459 {
460 vEnd=pPolygon[0];
461 }
462 else
463 {
464 vEnd=pPolygon[i+1];
465 }
466
467 if (pVoxelLimit.Inside(vStart))
468 {
469 if (pVoxelLimit.Inside(vEnd))
470 {
471 // vStart and vEnd inside -> output end point
472 //
473 outputPolygon.push_back(vEnd);
474 }
475 else
476 {
477 // vStart inside, vEnd outside -> output crossing point
478 //
479 pVoxelLimit.ClipToLimits(vStart,vEnd);
480 outputPolygon.push_back(vEnd);
481 }
482 }
483 else
484 {
485 if (pVoxelLimit.Inside(vEnd))
486 {
487 // vStart outside, vEnd inside -> output inside section
488 //
489 pVoxelLimit.ClipToLimits(vStart,vEnd);
490 outputPolygon.push_back(vStart);
491 outputPolygon.push_back(vEnd);
492 }
493 else // Both point outside -> no output
494 {
495 }
496 }
497 }
498}
@ FatalException
double G4double
Definition: G4Types.hh:64
int G4int
Definition: G4Types.hh:66
bool G4bool
Definition: G4Types.hh:67
double dot(const Hep3Vector &) const
virtual G4bool GetPlanerExtent(const G4ThreeVector &pointOnPlane, const G4ThreeVector &planeNormal, G4double &min, G4double &max) const
virtual G4bool Clip(const G4VoxelLimits &voxelLimit)
virtual G4bool PartialClip(const G4VoxelLimits &voxelLimit, const EAxis IgnoreMe)
G4ThreeVectorList vertices
void ClipToSimpleLimits(G4ThreeVectorList &pPolygon, G4ThreeVectorList &outputPolygon, const G4VoxelLimits &pVoxelLimit)
virtual const G4ThreeVector * GetMinPoint(const EAxis axis) const
virtual void AddVertexInOrder(const G4ThreeVector vertex)
virtual G4bool GetExtent(const EAxis axis, G4double &min, G4double &max) const
virtual void ClearAllVertices()
virtual void ClipAlongOneAxis(const G4VoxelLimits &voxelLimit, const EAxis axis)
virtual G4bool InFrontOf(const G4ClippablePolygon &other, EAxis axis) const
virtual G4bool BehindOf(const G4ClippablePolygon &other, EAxis axis) const
G4bool Empty() const
const G4ThreeVector GetNormal() const
virtual const G4ThreeVector * GetMaxPoint(const EAxis axis) const
G4double GetSurfaceTolerance() const
static G4GeometryTolerance * GetInstance()
G4double GetMinExtent(const EAxis pAxis) const
G4bool ClipToLimits(G4ThreeVector &pStart, G4ThreeVector &pEnd) const
void AddLimit(const EAxis pAxis, const G4double pMin, const G4double pMax)
G4double GetMaxExtent(const EAxis pAxis) const
G4bool Inside(const G4ThreeVector &pVec) const
G4bool IsLimited() const
EAxis
Definition: geomdefs.hh:54
@ kYAxis
Definition: geomdefs.hh:54
@ kXAxis
Definition: geomdefs.hh:54
@ kZAxis
Definition: geomdefs.hh:54
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *comments)
Definition: G4Exception.cc:41