Geant4 9.6.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4ReduciblePolygon.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// G4ReduciblePolygon.cc
35//
36// Implementation of a utility class used to specify, test, reduce,
37// and/or otherwise manipulate a 2D polygon.
38//
39// See G4ReduciblePolygon.hh for more info.
40//
41// --------------------------------------------------------------------
42
43#include "G4ReduciblePolygon.hh"
44#include "globals.hh"
45
46//
47// Constructor: with simple arrays
48//
50 const G4double b[],
51 G4int n )
52 : aMin(0.), aMax(0.), bMin(0.), bMax(0.),
53 vertexHead(0)
54{
55 //
56 // Do all of the real work in Create
57 //
58 Create( a, b, n );
59}
60
61
62//
63// Constructor: special PGON/PCON case
64//
66 const G4double rmax[],
67 const G4double z[], G4int n )
68 : aMin(0.), aMax(0.), bMin(0.), bMax(0.),
69 vertexHead(0)
70{
71 //
72 // Translate
73 //
74 G4double *a = new G4double[n*2];
75 G4double *b = new G4double[n*2];
76
77 G4double *rOut = a + n,
78 *zOut = b + n,
79 *rIn = rOut-1,
80 *zIn = zOut-1;
81
82 G4int i;
83 for( i=0; i < n; i++, rOut++, zOut++, rIn--, zIn-- )
84 {
85 *rOut = rmax[i];
86 *rIn = rmin[i];
87 *zOut = *zIn = z[i];
88 }
89
90 Create( a, b, n*2 );
91
92 delete [] a;
93 delete [] b;
94}
95
96
97//
98// Create
99//
100// To be called by constructors, fill in the list and statistics for a new
101// polygon
102//
104 const G4double b[], G4int n )
105{
106 if (n<3)
107 G4Exception("G4ReduciblePolygon::Create()", "GeomSolids0002",
108 FatalErrorInArgument, "Less than 3 vertices specified.");
109
110 const G4double *anext = a, *bnext = b;
111 ABVertex *prev = 0;
112 do
113 {
114 ABVertex *newVertex = new ABVertex;
115 newVertex->a = *anext;
116 newVertex->b = *bnext;
117 newVertex->next = 0;
118 if (prev==0)
119 {
120 vertexHead = newVertex;
121 }
122 else
123 {
124 prev->next = newVertex;
125 }
126
127 prev = newVertex;
128 } while( ++anext, ++bnext < b+n );
129
130 numVertices = n;
131
133}
134
135
136//
137// Fake default constructor - sets only member data and allocates memory
138// for usage restricted to object persistency.
139//
141 : aMin(0.), aMax(0.), bMin(0.), bMax(0.), numVertices(0), vertexHead(0)
142{
143}
144
145
146//
147// Destructor
148//
150{
151 ABVertex *curr = vertexHead;
152 while( curr )
153 {
154 ABVertex *toDelete = curr;
155 curr = curr->next;
156 delete toDelete;
157 }
158}
159
160
161//
162// CopyVertices
163//
164// Copy contents into simple linear arrays.
165// ***** CAUTION ***** Be care to declare the arrays to a large
166// enough size!
167//
169{
170 G4double *anext = a, *bnext = b;
171 ABVertex *curr = vertexHead;
172 while( curr )
173 {
174 *anext++ = curr->a;
175 *bnext++ = curr->b;
176 curr = curr->next;
177 }
178}
179
180
181//
182// ScaleA
183//
184// Multiply all a values by a common scale
185//
187{
188 ABVertex *curr = vertexHead;
189 while( curr )
190 {
191 curr->a *= scale;
192 curr = curr->next;
193 }
194}
195
196
197//
198// ScaleB
199//
200// Multiply all b values by a common scale
201//
203{
204 ABVertex *curr = vertexHead;
205 while( curr )
206 {
207 curr->b *= scale;
208 curr = curr->next;
209 }
210}
211
212
213//
214// RemoveDuplicateVertices
215//
216// Remove adjacent vertices that are equal. Returns "false" if there
217// is a problem (too few vertices remaining).
218//
220{
221 ABVertex *curr = vertexHead,
222 *prev = 0, *next = 0;
223 while( curr )
224 {
225 next = curr->next;
226 if (next == 0) next = vertexHead;
227
228 if (std::fabs(curr->a-next->a) < tolerance &&
229 std::fabs(curr->b-next->b) < tolerance )
230 {
231 //
232 // Duplicate found: do we have > 3 vertices?
233 //
234 if (numVertices <= 3)
235 {
237 return false;
238 }
239
240 //
241 // Delete
242 //
243 ABVertex *toDelete = curr;
244 curr = curr->next;
245 delete toDelete;
246
247 numVertices--;
248
249 if (prev) prev->next = curr; else vertexHead = curr;
250 }
251 else
252 {
253 prev = curr;
254 curr = curr->next;
255 }
256 }
257
258 //
259 // In principle, this is not needed, but why not just play it safe?
260 //
262
263 return true;
264}
265
266
267//
268// RemoveRedundantVertices
269//
270// Remove any unneeded vertices, i.e. those vertices which
271// are on the line connecting the previous and next vertices.
272//
274{
275 //
276 // Under these circumstances, we can quit now!
277 //
278 if (numVertices <= 2) return false;
279
280 G4double tolerance2 = tolerance*tolerance;
281
282 //
283 // Loop over all vertices
284 //
285 ABVertex *curr = vertexHead, *next = 0;
286 while( curr )
287 {
288 next = curr->next;
289 if (next == 0) next = vertexHead;
290
291 G4double da = next->a - curr->a,
292 db = next->b - curr->b;
293
294 //
295 // Loop over all subsequent vertices, up to curr
296 //
297 for(;;)
298 {
299 //
300 // Get vertex after next
301 //
302 ABVertex *test = next->next;
303 if (test == 0) test = vertexHead;
304
305 //
306 // If we are back to the original vertex, stop
307 //
308 if (test==curr) break;
309
310 //
311 // Test for parallel line segments
312 //
313 G4double dat = test->a - curr->a,
314 dbt = test->b - curr->b;
315
316 if (std::fabs(dat*db-dbt*da)>tolerance2) break;
317
318 //
319 // Redundant vertex found: do we have > 3 vertices?
320 //
321 if (numVertices <= 3)
322 {
324 return false;
325 }
326
327 //
328 // Delete vertex pointed to by next. Carefully!
329 //
330 if (curr->next)
331 { // next is not head
332 if (next->next)
333 curr->next = test; // next is not tail
334 else
335 curr->next = 0; // New tail
336 }
337 else
338 vertexHead = test; // New head
339
340 if ((curr != next) && (next != test)) delete next;
341
342 numVertices--;
343
344 //
345 // Replace next by the vertex we just tested,
346 // and keep on going...
347 //
348 next = test;
349 da = dat; db = dbt;
350 }
351 curr = curr->next;
352 }
353
354 //
355 // In principle, this is not needed, but why not just play it safe?
356 //
358
359 return true;
360}
361
362
363//
364// ReverseOrder
365//
366// Reverse the order of the vertices
367//
369{
370 //
371 // Loop over all vertices
372 //
373 ABVertex *prev = vertexHead;
374 if (prev==0) return; // No vertices
375
376 ABVertex *curr = prev->next;
377 if (curr==0) return; // Just one vertex
378
379 //
380 // Our new tail
381 //
382 vertexHead->next = 0;
383
384 for(;;)
385 {
386 //
387 // Save pointer to next vertex (in original order)
388 //
389 ABVertex *save = curr->next;
390
391 //
392 // Replace it with a pointer to the previous one
393 // (in original order)
394 //
395 curr->next = prev;
396
397 //
398 // Last vertex?
399 //
400 if (save == 0) break;
401
402 //
403 // Next vertex
404 //
405 prev = curr;
406 curr = save;
407 }
408
409 //
410 // Our new head
411 //
412 vertexHead = curr;
413}
414
415
416//
417// CrossesItself
418//
419// Return "true" if the polygon crosses itself
420//
421// Warning: this routine is not very fast (runs as N**2)
422//
424{
425 G4double tolerance2 = tolerance*tolerance;
426 G4double one = 1.0-tolerance,
427 zero = tolerance;
428 //
429 // Top loop over line segments. By the time we finish
430 // with the second to last segment, we're done.
431 //
432 ABVertex *curr1 = vertexHead, *next1=0;
433 while (curr1->next)
434 {
435 next1 = curr1->next;
436 G4double da1 = next1->a-curr1->a,
437 db1 = next1->b-curr1->b;
438
439 //
440 // Inner loop over subsequent line segments
441 //
442 ABVertex *curr2 = next1->next;
443 while( curr2 )
444 {
445 ABVertex *next2 = curr2->next;
446 if (next2==0) next2 = vertexHead;
447 G4double da2 = next2->a-curr2->a,
448 db2 = next2->b-curr2->b;
449 G4double a12 = curr2->a-curr1->a,
450 b12 = curr2->b-curr1->b;
451
452 //
453 // Calculate intersection of the two lines
454 //
455 G4double deter = da1*db2 - db1*da2;
456 if (std::fabs(deter) > tolerance2)
457 {
458 G4double s1, s2;
459 s1 = (a12*db2-b12*da2)/deter;
460
461 if (s1 >= zero && s1 < one)
462 {
463 s2 = -(da1*b12-db1*a12)/deter;
464 if (s2 >= zero && s2 < one) return true;
465 }
466 }
467 curr2 = curr2->next;
468 }
469 curr1 = next1;
470 }
471 return false;
472}
473
474
475
476//
477// BisectedBy
478//
479// Decide if a line through two points crosses the polygon, within tolerance
480//
482 G4double a2, G4double b2,
483 G4double tolerance )
484{
485 G4int nNeg = 0, nPos = 0;
486
487 G4double a12 = a2-a1, b12 = b2-b1;
488 G4double len12 = std::sqrt( a12*a12 + b12*b12 );
489 a12 /= len12; b12 /= len12;
490
491 ABVertex *curr = vertexHead;
492 do
493 {
494 G4double av = curr->a - a1,
495 bv = curr->b - b1;
496
497 G4double cross = av*b12 - bv*a12;
498
499 if (cross < -tolerance)
500 {
501 if (nPos) return true;
502 nNeg++;
503 }
504 else if (cross > tolerance)
505 {
506 if (nNeg) return true;
507 nPos++;
508 }
509 curr = curr->next;
510 } while( curr );
511
512 return false;
513}
514
515
516
517//
518// Area
519//
520// Calculated signed polygon area, where polygons specified in a
521// clockwise manner (where x==a, y==b) have negative area
522//
523// References: [O' Rourke (C)] pp. 18-27; [Gems II] pp. 5-6:
524// "The Area of a Simple Polygon", Jon Rokne.
525//
527{
528 G4double answer = 0;
529
530 ABVertex *curr = vertexHead, *next;
531 do
532 {
533 next = curr->next;
534 if (next==0) next = vertexHead;
535
536 answer += curr->a*next->b - curr->b*next->a;
537 curr = curr->next;
538 } while( curr );
539
540 return 0.5*answer;
541}
542
543
544//
545// Print
546//
548{
549 ABVertex *curr = vertexHead;
550 do
551 {
552 G4cerr << curr->a << " " << curr->b << G4endl;
553 curr = curr->next;
554 } while( curr );
555}
556
557
558//
559// CalculateMaxMin
560//
561// To be called when the vertices are changed, this
562// routine re-calculates global values
563//
565{
566 ABVertex *curr = vertexHead;
567 aMin = aMax = curr->a;
568 bMin = bMax = curr->b;
569 curr = curr->next;
570 while( curr )
571 {
572 if (curr->a < aMin)
573 aMin = curr->a;
574 else if (curr->a > aMax)
575 aMax = curr->a;
576
577 if (curr->b < bMin)
578 bMin = curr->b;
579 else if (curr->b > bMax)
580 bMax = curr->b;
581
582 curr = curr->next;
583 }
584}
@ FatalErrorInArgument
double G4double
Definition: G4Types.hh:64
int G4int
Definition: G4Types.hh:66
bool G4bool
Definition: G4Types.hh:67
#define G4endl
Definition: G4ios.hh:52
G4DLLIMPORT std::ostream G4cerr
G4ReduciblePolygon(const G4double a[], const G4double b[], G4int n)
G4bool BisectedBy(G4double a1, G4double b1, G4double a2, G4double b2, G4double tolerance)
void Create(const G4double a[], const G4double b[], G4int n)
void ScaleB(G4double scale)
void CopyVertices(G4double a[], G4double b[]) const
G4bool RemoveDuplicateVertices(G4double tolerance)
G4bool RemoveRedundantVertices(G4double tolerance)
G4bool CrossesItself(G4double tolerance)
void ScaleA(G4double scale)
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *comments)
Definition: G4Exception.cc:41