Geant4  v4-10.4-release
 모두 클래스 네임스페이스들 파일들 함수 변수 타입정의 열거형 타입 열거형 멤버 Friends 매크로 그룹들 페이지들
G4TessellatedSolid.cc
이 파일의 문서화 페이지로 가기
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 and of QinetiQ Ltd, *
20 // * subject to DEFCON 705 IPR conditions. *
21 // * By using, copying, modifying or distributing the software (or *
22 // * any work based on the software) you agree to acknowledge its *
23 // * use in resulting scientific publications, and indicate your *
24 // * acceptance of all terms of the Geant4 Software license. *
25 // ********************************************************************
26 //
27 // $Id: G4TessellatedSolid.cc 108288 2018-01-31 09:36:41Z gcosmo $
28 //
29 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
30 //
31 // CHANGE HISTORY
32 // --------------
33 // 23 October 2016, E Tcherniaev, reimplemented CalculateExtent() to make
34 // use of G4BoundingEnvelope.
35 //
36 // 12 October 2012, M Gayer, CERN, complete rewrite reducing memory
37 // requirements more than 50% and speedup by a factor of
38 // tens or more depending on the number of facets, thanks
39 // to voxelization of surface and improvements.
40 // Speedup factor of thousands for solids with number of
41 // facets in hundreds of thousands.
42 //
43 // 22 August 2011, I Hrivnacova, Orsay, fix in DistanceToOut(p) and
44 // DistanceToIn(p) to exactly compute distance from facet
45 // avoiding use of 'outgoing' flag shortcut variant.
46 //
47 // 04 August 2011, T Nikitina, CERN, added SetReferences() to
48 // CreatePolyhedron() for Visualization of Boolean Operations
49 //
50 // 12 April 2010, P R Truscott, QinetiQ, bug fixes to treat optical
51 // photon transport, in particular internal reflection
52 // at surface.
53 //
54 // 14 November 2007, P R Truscott, QinetiQ & Stan Seibert, U Texas
55 // Bug fixes to CalculateExtent
56 //
57 // 17 September 2007, P R Truscott, QinetiQ Ltd & Richard Holmberg
58 // Updated extensively prior to this date to deal with
59 // concaved tessellated surfaces, based on the algorithm
60 // of Richard Holmberg. This had been slightly modified
61 // to determine with inside the geometry by projecting
62 // random rays from the point provided. Now random rays
63 // are predefined rather than making use of random
64 // number generator at run-time.
65 //
66 // 22 November 2005, F Lei
67 // - Changed ::DescribeYourselfTo(), line 464
68 // - added GetPolyHedron()
69 //
70 // 31 October 2004, P R Truscott, QinetiQ Ltd, UK
71 // - Created.
72 //
73 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
74 
75 #include "G4TessellatedSolid.hh"
76 
77 #if !defined(G4GEOM_USE_UTESSELLATEDSOLID)
78 
79 #include <iostream>
80 #include <stack>
81 #include <iostream>
82 #include <iomanip>
83 #include <fstream>
84 #include <algorithm>
85 #include <list>
86 
87 #include "geomdefs.hh"
88 #include "Randomize.hh"
89 #include "G4SystemOfUnits.hh"
90 #include "G4PhysicalConstants.hh"
91 #include "G4GeometryTolerance.hh"
92 #include "G4VFacet.hh"
93 #include "G4VoxelLimits.hh"
94 #include "G4AffineTransform.hh"
95 #include "G4BoundingEnvelope.hh"
96 
97 #include "G4PolyhedronArbitrary.hh"
98 #include "G4VGraphicsScene.hh"
99 #include "G4VisExtent.hh"
100 
101 #include "G4AutoLock.hh"
102 
103 namespace
104 {
105  G4Mutex polyhedronMutex = G4MUTEX_INITIALIZER;
106 }
107 
108 using namespace std;
109 
111 //
112 // Standard contructor has blank name and defines no fFacets.
113 //
115 {
116  Initialize();
117 }
118 
120 //
121 // Alternative constructor. Simple define name and geometry type - no fFacets
122 // to detine.
123 //
125  : G4VSolid(name)
126 {
127  Initialize();
128 }
129 
131 //
132 // Fake default constructor - sets only member data and allocates memory
133 // for usage restricted to object persistency.
134 //
136 {
137  Initialize();
138  fMinExtent.set(0,0,0);
139  fMaxExtent.set(0,0,0);
140 }
141 
142 
145 {
146  DeleteObjects ();
147 }
148 
150 //
151 // Copy constructor.
152 //
154  : G4VSolid(ts), fpPolyhedron(0)
155 {
156  Initialize();
157 
158  CopyObjects(ts);
159 }
160 
162 //
163 // Assignment operator.
164 //
167 {
168  if (&ts == this) return *this;
169 
170  // Copy base class data
172 
173  DeleteObjects ();
174 
175  Initialize();
176 
177  CopyObjects (ts);
178 
179  return *this;
180 }
181 
183 //
185 {
187 
188  fRebuildPolyhedron = false; fpPolyhedron = 0;
189  fCubicVolume = 0.; fSurfaceArea = 0.;
190 
191  fGeometryType = "G4TessellatedSolid";
192  fSolidClosed = false;
193 
196 
198 }
199 
201 //
203 {
204  G4int size = fFacets.size();
205  for (G4int i = 0; i < size; ++i) { delete fFacets[i]; }
206  fFacets.clear();
207  delete fpPolyhedron; fpPolyhedron = 0;
208 }
209 
211 //
213 {
214  G4ThreeVector reductionRatio;
215  G4int fmaxVoxels = fVoxels.GetMaxVoxels(reductionRatio);
216  if (fmaxVoxels < 0)
217  fVoxels.SetMaxVoxels(reductionRatio);
218  else
219  fVoxels.SetMaxVoxels(fmaxVoxels);
220 
221  G4int n = ts.GetNumberOfFacets();
222  for (G4int i = 0; i < n; ++i)
223  {
224  G4VFacet *facetClone = (ts.GetFacet(i))->GetClone();
225  AddFacet(facetClone);
226  }
227  if (ts.GetSolidClosed()) SetSolidClosed(true);
228 }
229 
231 //
232 // Add a facet to the facet list.
233 // Note that you can add, but you cannot delete.
234 //
236 {
237  // Add the facet to the vector.
238  //
239  if (fSolidClosed)
240  {
241  G4Exception("G4TessellatedSolid::AddFacet()", "GeomSolids1002",
242  JustWarning, "Attempt to add facets when solid is closed.");
243  return false;
244  }
245  else if (aFacet->IsDefined())
246  {
247  set<G4VertexInfo,G4VertexComparator>::iterator begin
248  = fFacetList.begin(), end = fFacetList.end(), pos, it;
249  G4ThreeVector p = aFacet->GetCircumcentre();
251  value.id = fFacetList.size();
252  value.mag2 = p.x() + p.y() + p.z();
253 
254  G4bool found = false;
256  {
257  G4double kCarTolerance3 = 3 * kCarTolerance;
258  pos = fFacetList.lower_bound(value);
259 
260  it = pos;
261  while (!found && it != end) // Loop checking, 13.08.2015, G.Cosmo
262  {
263  G4int id = (*it).id;
264  G4VFacet *facet = fFacets[id];
265  G4ThreeVector q = facet->GetCircumcentre();
266  if ((found = (facet == aFacet))) break;
267  G4double dif = q.x() + q.y() + q.z() - value.mag2;
268  if (dif > kCarTolerance3) break;
269  it++;
270  }
271 
272  if (fFacets.size() > 1)
273  {
274  it = pos;
275  while (!found && it != begin) // Loop checking, 13.08.2015, G.Cosmo
276  {
277  --it;
278  G4int id = (*it).id;
279  G4VFacet *facet = fFacets[id];
280  G4ThreeVector q = facet->GetCircumcentre();
281  found = (facet == aFacet);
282  if (found) break;
283  G4double dif = value.mag2 - (q.x() + q.y() + q.z());
284  if (dif > kCarTolerance3) break;
285  }
286  }
287  }
288 
289  if (!found)
290  {
291  fFacets.push_back(aFacet);
292  fFacetList.insert(value);
293  }
294 
295  return true;
296  }
297  else
298  {
299  G4Exception("G4TessellatedSolid::AddFacet()", "GeomSolids1002",
300  JustWarning, "Attempt to add facet not properly defined.");
301  aFacet->StreamInfo(G4cout);
302  return false;
303  }
304 }
305 
307 //
308 G4int G4TessellatedSolid::SetAllUsingStack(const std::vector<G4int> &voxel,
309  const std::vector<G4int> &max,
310  G4bool status, G4SurfBits &checked)
311 {
312  vector<G4int> xyz = voxel;
313  stack<vector<G4int> > pos;
314  pos.push(xyz);
315  G4int filled = 0;
316  G4int cc = 0, nz = 0;
317 
318  vector<G4int> candidates;
319 
320  while (!pos.empty()) // Loop checking, 13.08.2015, G.Cosmo
321  {
322  xyz = pos.top();
323  pos.pop();
324  G4int index = fVoxels.GetVoxelsIndex(xyz);
325  if (!checked[index])
326  {
327  checked.SetBitNumber(index, true);
328  cc++;
329 
330  if (fVoxels.IsEmpty(index))
331  {
332  filled++;
333 
334  fInsides.SetBitNumber(index, status);
335 
336  for (G4int i = 0; i <= 2; ++i)
337  {
338  if (xyz[i] < max[i] - 1)
339  {
340  xyz[i]++;
341  pos.push(xyz);
342  xyz[i]--;
343  }
344 
345  if (xyz[i] > 0)
346  {
347  xyz[i]--;
348  pos.push(xyz);
349  xyz[i]++;
350  }
351  }
352  }
353  else
354  {
355  nz++;
356  }
357  }
358  }
359  return filled;
360 }
361 
363 //
365 {
366  vector<G4int> voxel(3), maxVoxels(3);
367  for (G4int i = 0; i <= 2; ++i) maxVoxels[i] = fVoxels.GetBoundary(i).size();
368  G4int size = maxVoxels[0] * maxVoxels[1] * maxVoxels[2];
369 
370  G4SurfBits checked(size-1);
371  fInsides.Clear();
372  fInsides.ResetBitNumber(size-1);
373 
374  G4ThreeVector point;
375  for (voxel[2] = 0; voxel[2] < maxVoxels[2] - 1; ++voxel[2])
376  {
377  for (voxel[1] = 0; voxel[1] < maxVoxels[1] - 1; ++voxel[1])
378  {
379  for (voxel[0] = 0; voxel[0] < maxVoxels[0] - 1; ++voxel[0])
380  {
381  G4int index = fVoxels.GetVoxelsIndex(voxel);
382  if (!checked[index] && fVoxels.IsEmpty(index))
383  {
384  for (G4int i = 0; i <= 2; ++i)
385  {
386  point[i] = fVoxels.GetBoundary(i)[voxel[i]];
387  }
388  G4bool inside = (G4bool) (InsideNoVoxels(point) == kInside);
389  SetAllUsingStack(voxel, maxVoxels, inside, checked);
390  }
391  else checked.SetBitNumber(index);
392  }
393  }
394  }
395 }
396 
398 //
400 {
401 #ifdef G4SPECSDEBUG
402  G4cout << "Voxelizing..." << G4endl;
403 #endif
405 
406  if (fVoxels.Empty().GetNbits())
407  {
408 #ifdef G4SPECSDEBUG
409  G4cout << "Precalculating Insides..." << G4endl;
410 #endif
412  }
413 }
414 
416 //
417 // Compute extremeFacets, i.e. find those facets that have surface
418 // planes that bound the volume.
419 // Note that this is going to reject concaved surfaces as being extreme. Also
420 // note that if the vertex is on the facet, displacement is zero, so IsInside
421 // returns true. So will this work?? Need non-equality
422 // "G4bool inside = displacement < 0.0;"
423 // or
424 // "G4bool inside = displacement <= -0.5*kCarTolerance"
425 // (Notes from PT 13/08/2007).
426 //
428 {
429  G4int size = fFacets.size();
430  for (G4int j = 0; j < size; ++j)
431  {
432  G4VFacet &facet = *fFacets[j];
433 
434  G4bool isExtreme = true;
435  G4int vsize = fVertexList.size();
436  for (G4int i=0; i < vsize; ++i)
437  {
438  if (!facet.IsInside(fVertexList[i]))
439  {
440  isExtreme = false;
441  break;
442  }
443  }
444  if (isExtreme) fExtremeFacets.insert(&facet);
445  }
446 }
447 
449 //
451 {
452  // The algorithm:
453  // we will have additional vertexListSorted, where all the items will be
454  // sorted by magnitude of vertice vector.
455  // New candidate for fVertexList - we will determine the position fo first
456  // item which would be within its magnitude - 0.5*kCarTolerance.
457  // We will go trough until we will reach > +0.5 kCarTolerance.
458  // Comparison (q-p).mag() < 0.5*kCarTolerance will be made.
459  // They can be just stored in std::vector, with custom insertion based
460  // on binary search.
461 
462  set<G4VertexInfo,G4VertexComparator> vertexListSorted;
463  set<G4VertexInfo,G4VertexComparator>::iterator begin
464  = vertexListSorted.begin(), end = vertexListSorted.end(), pos, it;
467 
468  fVertexList.clear();
469  G4int size = fFacets.size();
470 
471  G4double kCarTolerance24 = kCarTolerance * kCarTolerance / 4.0;
472  G4double kCarTolerance3 = 3 * kCarTolerance;
473  vector<G4int> newIndex(100);
474 
475  for (G4int k = 0; k < size; ++k)
476  {
477  G4VFacet &facet = *fFacets[k];
478  G4int max = facet.GetNumberOfVertices();
479 
480  for (G4int i = 0; i < max; ++i)
481  {
482  p = facet.GetVertex(i);
483  value.id = fVertexList.size();
484  value.mag2 = p.x() + p.y() + p.z();
485 
486  G4bool found = false;
487  G4int id = 0;
489  {
490  pos = vertexListSorted.lower_bound(value);
491  it = pos;
492  while (it != end) // Loop checking, 13.08.2015, G.Cosmo
493  {
494  id = (*it).id;
495  G4ThreeVector q = fVertexList[id];
496  G4double dif = (q-p).mag2();
497  found = (dif < kCarTolerance24);
498  if (found) break;
499  dif = q.x() + q.y() + q.z() - value.mag2;
500  if (dif > kCarTolerance3) break;
501  it++;
502  }
503 
504  if (!found && (fVertexList.size() > 1))
505  {
506  it = pos;
507  while (it != begin) // Loop checking, 13.08.2015, G.Cosmo
508  {
509  --it;
510  id = (*it).id;
511  G4ThreeVector q = fVertexList[id];
512  G4double dif = (q-p).mag2();
513  found = (dif < kCarTolerance24);
514  if (found) break;
515  dif = value.mag2 - (q.x() + q.y() + q.z());
516  if (dif > kCarTolerance3) break;
517  }
518  }
519  }
520 
521  if (!found)
522  {
523 #ifdef G4SPECSDEBUG
524  G4cout << p.x() << ":" << p.y() << ":" << p.z() << G4endl;
525  G4cout << "Adding new vertex #" << i << " of facet " << k
526  << " id " << value.id << G4endl;
527  G4cout << "===" << G4endl;
528 #endif
529  fVertexList.push_back(p);
530  vertexListSorted.insert(value);
531  begin = vertexListSorted.begin();
532  end = vertexListSorted.end();
533  newIndex[i] = value.id;
534  //
535  // Now update the maximum x, y and z limits of the volume.
536  //
537  if (value.id == 0) fMinExtent = fMaxExtent = p;
538  else
539  {
540  if (p.x() > fMaxExtent.x()) fMaxExtent.setX(p.x());
541  else if (p.x() < fMinExtent.x()) fMinExtent.setX(p.x());
542  if (p.y() > fMaxExtent.y()) fMaxExtent.setY(p.y());
543  else if (p.y() < fMinExtent.y()) fMinExtent.setY(p.y());
544  if (p.z() > fMaxExtent.z()) fMaxExtent.setZ(p.z());
545  else if (p.z() < fMinExtent.z()) fMinExtent.setZ(p.z());
546  }
547  }
548  else
549  {
550 #ifdef G4SPECSDEBUG
551  G4cout << p.x() << ":" << p.y() << ":" << p.z() << G4endl;
552  G4cout << "Vertex #" << i << " of facet " << k
553  << " found, redirecting to " << id << G4endl;
554  G4cout << "===" << G4endl;
555 #endif
556  newIndex[i] = id;
557  }
558  }
559  // only now it is possible to change vertices pointer
560  //
561  facet.SetVertices(&fVertexList);
562  for (G4int i = 0; i < max; i++)
563  facet.SetVertexIndex(i,newIndex[i]);
564  }
565  vector<G4ThreeVector>(fVertexList).swap(fVertexList);
566 
567 #ifdef G4SPECSDEBUG
568  G4double previousValue = 0;
569  for (set<G4VertexInfo,G4VertexComparator>::iterator res=
570  vertexListSorted.begin(); res!=vertexListSorted.end(); ++res)
571  {
572  G4int id = (*res).id;
573  G4ThreeVector vec = fVertexList[id];
574  G4double mvalue = vec.x() + vec.y() + vec.z();
575  if (previousValue && (previousValue - 1e-9 > mvalue))
576  G4cout << "Error in CreateVertexList: previousValue " << previousValue
577  << " is smaller than mvalue " << mvalue << G4endl;
578  previousValue = mvalue;
579  }
580 #endif
581 }
582 
584 //
586 {
588  G4int with = AllocatedMemory();
589  G4double ratio = (G4double) with / without;
590  G4cout << "G4TessellatedSolid - Allocated memory without voxel overhead "
591  << without << "; with " << with << "; ratio: " << ratio << G4endl;
592 }
593 
595 //
597 {
598  if (t)
599  {
600 #ifdef G4SPECSDEBUG
601  G4cout << "Creating vertex list..." << G4endl;
602 #endif
604 
605 #ifdef G4SPECSDEBUG
606  G4cout << "Setting extreme facets..." << G4endl;
607 #endif
609 
610 #ifdef G4SPECSDEBUG
611  G4cout << "Voxelizing..." << G4endl;
612 #endif
613  Voxelize();
614 
615 #ifdef G4SPECSDEBUG
617 #endif
618 
619  }
620  fSolidClosed = t;
621 }
622 
624 //
625 // GetSolidClosed
626 //
627 // Used to determine whether the solid is closed to adding further fFacets.
628 //
630 {
631  return fSolidClosed;
632 }
633 
635 //
636 // operator+=
637 //
638 // This operator allows the user to add two tessellated solids together, so
639 // that the solid on the left then includes all of the facets in the solid
640 // on the right. Note that copies of the facets are generated, rather than
641 // using the original facet set of the solid on the right.
642 //
645 {
646  G4int size = right.GetNumberOfFacets();
647  for (G4int i = 0; i < size; ++i)
648  AddFacet(right.GetFacet(i)->GetClone());
649 
650  return *this;
651 }
652 
654 //
655 // GetNumberOfFacets
656 //
658 {
659  return fFacets.size();
660 }
661 
663 //
665 {
666  //
667  // First the simple test - check if we're outside of the X-Y-Z extremes
668  // of the tessellated solid.
669  //
671  return kOutside;
672 
673  vector<G4int> startingVoxel(3);
674  fVoxels.GetVoxel(startingVoxel, p);
675 
676  const G4double dirTolerance = 1.0E-14;
677 
678  const vector<G4int> &startingCandidates =
679  fVoxels.GetCandidates(startingVoxel);
680  G4int limit = startingCandidates.size();
681  if (limit == 0 && fInsides.GetNbits())
682  {
683  G4int index = fVoxels.GetPointIndex(p);
684  EInside location = fInsides[index] ? kInside : kOutside;
685  return location;
686  }
687 
688  G4double minDist = kInfinity;
689 
690  for(G4int i = 0; i < limit; ++i)
691  {
692  G4int candidate = startingCandidates[i];
693  G4VFacet &facet = *fFacets[candidate];
694  G4double dist = facet.Distance(p,minDist);
695  if (dist < minDist) minDist = dist;
696  if (dist <= kCarToleranceHalf)
697  return kSurface;
698  }
699 
700  // The following is something of an adaptation of the method implemented by
701  // Rickard Holmberg augmented with information from Schneider & Eberly,
702  // "Geometric Tools for Computer Graphics," pp700-701, 2003. In essence,
703  // we're trying to determine whether we're inside the volume by projecting
704  // a few rays and determining if the first surface crossed is has a normal
705  // vector between 0 to pi/2 (out-going) or pi/2 to pi (in-going).
706  // We should also avoid rays which are nearly within the plane of the
707  // tessellated surface, and therefore produce rays randomly.
708  // For the moment, this is a bit over-engineered (belt-braces-and-ducttape).
709  //
710  G4double distOut = kInfinity;
711  G4double distIn = kInfinity;
712  G4double distO = 0.0;
713  G4double distI = 0.0;
714  G4double distFromSurfaceO = 0.0;
715  G4double distFromSurfaceI = 0.0;
716  G4ThreeVector normalO, normalI;
717  G4bool crossingO = false;
718  G4bool crossingI = false;
719  EInside location = kOutside;
720  G4int sm = 0;
721 
722  G4bool nearParallel = false;
723  do // Loop checking, 13.08.2015, G.Cosmo
724  {
725  // We loop until we find direction where the vector is not nearly parallel
726  // to the surface of any facet since this causes ambiguities. The usual
727  // case is that the angles should be sufficiently different, but there
728  // are 20 random directions to select from - hopefully sufficient.
729  //
730  distOut = distIn = kInfinity;
731  const G4ThreeVector &v = fRandir[sm];
732  sm++;
733  //
734  // This code could be voxelized by the same algorithm, which is used for
735  // DistanceToOut(). We will traverse through fVoxels. we will call
736  // intersect only for those, which would be candidates and was not
737  // checked before.
738  //
739  G4ThreeVector currentPoint = p;
740  G4ThreeVector direction = v.unit();
741  // G4SurfBits exclusion(fVoxels.GetBitsPerSlice());
742  vector<G4int> curVoxel(3);
743  curVoxel = startingVoxel;
744  G4double shiftBonus = kCarTolerance;
745 
746  G4bool crossed = false;
747  G4bool started = true;
748 
749  do // Loop checking, 13.08.2015, G.Cosmo
750  {
751  const vector<G4int> &candidates =
752  started ? startingCandidates : fVoxels.GetCandidates(curVoxel);
753  started = false;
754  if (G4int candidatesCount = candidates.size())
755  {
756  for (G4int i = 0 ; i < candidatesCount; ++i)
757  {
758  G4int candidate = candidates[i];
759  // bits.SetBitNumber(candidate);
760  G4VFacet &facet = *fFacets[candidate];
761 
762  crossingO = facet.Intersect(p,v,true,distO,distFromSurfaceO,normalO);
763  crossingI = facet.Intersect(p,v,false,distI,distFromSurfaceI,normalI);
764 
765  if (crossingO || crossingI)
766  {
767  crossed = true;
768 
769  nearParallel = (crossingO
770  && std::fabs(normalO.dot(v))<dirTolerance)
771  || (crossingI && std::fabs(normalI.dot(v))<dirTolerance);
772  if (!nearParallel)
773  {
774  if (crossingO && distO > 0.0 && distO < distOut)
775  distOut = distO;
776  if (crossingI && distI > 0.0 && distI < distIn)
777  distIn = distI;
778  }
779  else break;
780  }
781  }
782  if (nearParallel) break;
783  }
784  else
785  {
786  if (!crossed)
787  {
788  G4int index = fVoxels.GetVoxelsIndex(curVoxel);
789  G4bool inside = fInsides[index];
790  location = inside ? kInside : kOutside;
791  return location;
792  }
793  }
794 
795  G4double shift=fVoxels.DistanceToNext(currentPoint, direction, curVoxel);
796  if (shift == kInfinity) break;
797 
798  currentPoint += direction * (shift + shiftBonus);
799  }
800  while (fVoxels.UpdateCurrentVoxel(currentPoint, direction, curVoxel));
801 
802  }
803  while (nearParallel && sm!=fMaxTries);
804  //
805  // Here we loop through the facets to find out if there is an intersection
806  // between the ray and that facet. The test if performed separately whether
807  // the ray is entering the facet or exiting.
808  //
809 #ifdef G4VERBOSE
810  if (sm == fMaxTries)
811  {
812  //
813  // We've run out of random vector directions. If nTries is set sufficiently
814  // low (nTries <= 0.5*maxTries) then this would indicate that there is
815  // something wrong with geometry.
816  //
817  std::ostringstream message;
818  G4int oldprc = message.precision(16);
819  message << "Cannot determine whether point is inside or outside volume!"
820  << G4endl
821  << "Solid name = " << GetName() << G4endl
822  << "Geometry Type = " << fGeometryType << G4endl
823  << "Number of facets = " << fFacets.size() << G4endl
824  << "Position:" << G4endl << G4endl
825  << "p.x() = " << p.x()/mm << " mm" << G4endl
826  << "p.y() = " << p.y()/mm << " mm" << G4endl
827  << "p.z() = " << p.z()/mm << " mm";
828  message.precision(oldprc);
829  G4Exception("G4TessellatedSolid::Inside()",
830  "GeomSolids1002", JustWarning, message);
831  }
832 #endif
833 
834  // In the next if-then-elseif G4String the logic is as follows:
835  // (1) You don't hit anything so cannot be inside volume, provided volume
836  // constructed correctly!
837  // (2) Distance to inside (ie. nearest facet such that you enter facet) is
838  // shorter than distance to outside (nearest facet such that you exit
839  // facet) - on condition of safety distance - therefore we're outside.
840  // (3) Distance to outside is shorter than distance to inside therefore
841  // we're inside.
842  //
843  if (distIn == kInfinity && distOut == kInfinity)
844  location = kOutside;
845  else if (distIn <= distOut - kCarToleranceHalf)
846  location = kOutside;
847  else if (distOut <= distIn - kCarToleranceHalf)
848  location = kInside;
849 
850  return location;
851 }
852 
854 //
856 {
857  //
858  // First the simple test - check if we're outside of the X-Y-Z extremes
859  // of the tessellated solid.
860  //
862  return kOutside;
863 
864  const G4double dirTolerance = 1.0E-14;
865 
866  G4double minDist = kInfinity;
867  //
868  // Check if we are close to a surface
869  //
870  G4int size = fFacets.size();
871  for (G4int i = 0; i < size; ++i)
872  {
873  G4VFacet &facet = *fFacets[i];
874  G4double dist = facet.Distance(p,minDist);
875  if (dist < minDist) minDist = dist;
876  if (dist <= kCarToleranceHalf)
877  {
878  return kSurface;
879  }
880  }
881  //
882  // The following is something of an adaptation of the method implemented by
883  // Rickard Holmberg augmented with information from Schneider & Eberly,
884  // "Geometric Tools for Computer Graphics," pp700-701, 2003. In essence, we're
885  // trying to determine whether we're inside the volume by projecting a few
886  // rays and determining if the first surface crossed is has a normal vector
887  // between 0 to pi/2 (out-going) or pi/2 to pi (in-going). We should also
888  // avoid rays which are nearly within the plane of the tessellated surface,
889  // and therefore produce rays randomly. For the moment, this is a bit
890  // over-engineered (belt-braces-and-ducttape).
891  //
892 #if G4SPECSDEBUG
893  G4int nTry = 7;
894 #else
895  G4int nTry = 3;
896 #endif
897  G4double distOut = kInfinity;
898  G4double distIn = kInfinity;
899  G4double distO = 0.0;
900  G4double distI = 0.0;
901  G4double distFromSurfaceO = 0.0;
902  G4double distFromSurfaceI = 0.0;
903  G4ThreeVector normalO(0.0,0.0,0.0);
904  G4ThreeVector normalI(0.0,0.0,0.0);
905  G4bool crossingO = false;
906  G4bool crossingI = false;
907  EInside location = kOutside;
908  EInside locationprime = kOutside;
909  G4int sm = 0;
910 
911  for (G4int i=0; i<nTry; ++i)
912  {
913  G4bool nearParallel = false;
914  do // Loop checking, 13.08.2015, G.Cosmo
915  {
916  //
917  // We loop until we find direction where the vector is not nearly parallel
918  // to the surface of any facet since this causes ambiguities. The usual
919  // case is that the angles should be sufficiently different, but there
920  // are 20 random directions to select from - hopefully sufficient.
921  //
922  distOut = distIn = kInfinity;
923  G4ThreeVector v = fRandir[sm];
924  sm++;
925  vector<G4VFacet*>::const_iterator f = fFacets.begin();
926 
927  do // Loop checking, 13.08.2015, G.Cosmo
928  {
929  //
930  // Here we loop through the facets to find out if there is an
931  // intersection between the ray and that facet. The test if performed
932  // separately whether the ray is entering the facet or exiting.
933  //
934  crossingO = ((*f)->Intersect(p,v,true,distO,distFromSurfaceO,normalO));
935  crossingI = ((*f)->Intersect(p,v,false,distI,distFromSurfaceI,normalI));
936  if (crossingO || crossingI)
937  {
938  nearParallel = (crossingO && std::fabs(normalO.dot(v))<dirTolerance)
939  || (crossingI && std::fabs(normalI.dot(v))<dirTolerance);
940  if (!nearParallel)
941  {
942  if (crossingO && distO > 0.0 && distO < distOut) distOut = distO;
943  if (crossingI && distI > 0.0 && distI < distIn) distIn = distI;
944  }
945  }
946  } while (!nearParallel && ++f!=fFacets.end());
947  } while (nearParallel && sm!=fMaxTries);
948 
949 #ifdef G4VERBOSE
950  if (sm == fMaxTries)
951  {
952  //
953  // We've run out of random vector directions. If nTries is set
954  // sufficiently low (nTries <= 0.5*maxTries) then this would indicate
955  // that there is something wrong with geometry.
956  //
957  std::ostringstream message;
958  G4int oldprc = message.precision(16);
959  message << "Cannot determine whether point is inside or outside volume!"
960  << G4endl
961  << "Solid name = " << GetName() << G4endl
962  << "Geometry Type = " << fGeometryType << G4endl
963  << "Number of facets = " << fFacets.size() << G4endl
964  << "Position:" << G4endl << G4endl
965  << "p.x() = " << p.x()/mm << " mm" << G4endl
966  << "p.y() = " << p.y()/mm << " mm" << G4endl
967  << "p.z() = " << p.z()/mm << " mm";
968  message.precision(oldprc);
969  G4Exception("G4TessellatedSolid::Inside()",
970  "GeomSolids1002", JustWarning, message);
971  }
972 #endif
973  //
974  // In the next if-then-elseif G4String the logic is as follows:
975  // (1) You don't hit anything so cannot be inside volume, provided volume
976  // constructed correctly!
977  // (2) Distance to inside (ie. nearest facet such that you enter facet) is
978  // shorter than distance to outside (nearest facet such that you exit
979  // facet) - on condition of safety distance - therefore we're outside.
980  // (3) Distance to outside is shorter than distance to inside therefore
981  // we're inside.
982  //
983  if (distIn == kInfinity && distOut == kInfinity)
984  locationprime = kOutside;
985  else if (distIn <= distOut - kCarToleranceHalf)
986  locationprime = kOutside;
987  else if (distOut <= distIn - kCarToleranceHalf)
988  locationprime = kInside;
989 
990  if (i == 0) location = locationprime;
991  }
992 
993  return location;
994 }
995 
997 //
998 // Return the outwards pointing unit normal of the shape for the
999 // surface closest to the point at offset p.
1000 //
1002  G4ThreeVector &aNormal) const
1003 {
1004  G4double minDist;
1005  G4VFacet *facet = 0;
1006 
1007  if (fVoxels.GetCountOfVoxels() > 1)
1008  {
1009  vector<G4int> curVoxel(3);
1010  fVoxels.GetVoxel(curVoxel, p);
1011  const vector<G4int> &candidates = fVoxels.GetCandidates(curVoxel);
1012  // fVoxels.GetCandidatesVoxelArray(p, candidates, 0);
1013 
1014  if (G4int limit = candidates.size())
1015  {
1016  minDist = kInfinity;
1017  for(G4int i = 0 ; i < limit ; ++i)
1018  {
1019  G4int candidate = candidates[i];
1020  G4VFacet &fct = *fFacets[candidate];
1021  G4double dist = fct.Distance(p,minDist);
1022  if (dist < minDist) minDist = dist;
1023  if (dist <= kCarToleranceHalf)
1024  {
1025  aNormal = fct.GetSurfaceNormal();
1026  return true;
1027  }
1028  }
1029  }
1030  minDist = MinDistanceFacet(p, true, facet);
1031  }
1032  else
1033  {
1034  minDist = kInfinity;
1035  G4int size = fFacets.size();
1036  for (G4int i = 0; i < size; ++i)
1037  {
1038  G4VFacet &f = *fFacets[i];
1039  G4double dist = f.Distance(p, minDist);
1040  if (dist < minDist)
1041  {
1042  minDist = dist;
1043  facet = &f;
1044  }
1045  }
1046  }
1047 
1048  if (minDist != kInfinity)
1049  {
1050  if (facet) { aNormal = facet->GetSurfaceNormal(); }
1051  return minDist <= kCarToleranceHalf;
1052  }
1053  else
1054  {
1055 #ifdef G4VERBOSE
1056  std::ostringstream message;
1057  message << "Point p is not on surface !?" << G4endl
1058  << " No facets found for point: " << p << " !" << G4endl
1059  << " Returning approximated value for normal.";
1060 
1061  G4Exception("G4TessellatedSolid::SurfaceNormal(p)",
1062  "GeomSolids1002", JustWarning, message );
1063 #endif
1064  aNormal = (p.z() > 0 ? G4ThreeVector(0,0,1) : G4ThreeVector(0,0,-1));
1065  return false;
1066  }
1067 }
1068 
1070 //
1071 // G4double DistanceToIn(const G4ThreeVector& p, const G4ThreeVector& v)
1072 //
1073 // Return the distance along the normalised vector v to the shape,
1074 // from the point at offset p. If there is no intersection, return
1075 // kInfinity. The first intersection resulting from 'leaving' a
1076 // surface/volume is discarded. Hence, this is tolerant of points on
1077 // surface of shape.
1078 //
1079 G4double
1081  const G4ThreeVector &v,
1082  G4double /*aPstep*/) const
1083 {
1084  G4double minDist = kInfinity;
1085  G4double dist = 0.0;
1086  G4double distFromSurface = 0.0;
1088 
1089 #if G4SPECSDEBUG
1090  if (Inside(p) == kInside )
1091  {
1092  std::ostringstream message;
1093  G4int oldprc = message.precision(16) ;
1094  message << "Point p is already inside!?" << G4endl
1095  << "Position:" << G4endl << G4endl
1096  << " p.x() = " << p.x()/mm << " mm" << G4endl
1097  << " p.y() = " << p.y()/mm << " mm" << G4endl
1098  << " p.z() = " << p.z()/mm << " mm" << G4endl
1099  << "DistanceToOut(p) == " << DistanceToOut(p);
1100  message.precision(oldprc) ;
1101  G4Exception("G4TriangularFacet::DistanceToIn(p,v)",
1102  "GeomSolids1002", JustWarning, message);
1103  }
1104 #endif
1105 
1106  G4int size = fFacets.size();
1107  for (G4int i = 0; i < size; ++i)
1108  {
1109  G4VFacet &facet = *fFacets[i];
1110  if (facet.Intersect(p,v,false,dist,distFromSurface,normal))
1111  {
1112  //
1113  // set minDist to the new distance to current facet if distFromSurface
1114  // is in positive direction and point is not at surface. If the point is
1115  // within 0.5*kCarTolerance of the surface, then force distance to be
1116  // zero and leave member function immediately (for efficiency), as
1117  // proposed by & credit to Akira Okumura.
1118  //
1119  if (distFromSurface > kCarToleranceHalf && dist >= 0.0 && dist < minDist)
1120  {
1121  minDist = dist;
1122  }
1123  else
1124  {
1125  if (-kCarToleranceHalf <= dist && dist <= kCarToleranceHalf)
1126  {
1127  return 0.0;
1128  }
1129  else
1130  {
1131  if (distFromSurface > -kCarToleranceHalf
1132  && distFromSurface < kCarToleranceHalf)
1133  {
1134  minDist = dist;
1135  }
1136  }
1137  }
1138  }
1139  }
1140  return minDist;
1141 }
1142 
1144 //
1145 G4double
1147  const G4ThreeVector &v,
1148  G4ThreeVector &aNormalVector,
1149  G4bool &aConvex,
1150  G4double /*aPstep*/) const
1151 {
1152  G4double minDist = kInfinity;
1153  G4double dist = 0.0;
1154  G4double distFromSurface = 0.0;
1155  G4ThreeVector normal, minNormal;
1156 
1157 #if G4SPECSDEBUG
1158  if ( Inside(p) == kOutside )
1159  {
1160  std::ostringstream message;
1161  G4int oldprc = message.precision(16) ;
1162  message << "Point p is already outside!?" << G4endl
1163  << "Position:" << G4endl << G4endl
1164  << " p.x() = " << p.x()/mm << " mm" << G4endl
1165  << " p.y() = " << p.y()/mm << " mm" << G4endl
1166  << " p.z() = " << p.z()/mm << " mm" << G4endl
1167  << "DistanceToIn(p) == " << DistanceToIn(p);
1168  message.precision(oldprc) ;
1169  G4Exception("G4TriangularFacet::DistanceToOut(p)",
1170  "GeomSolids1002", JustWarning, message);
1171  }
1172 #endif
1173 
1174  G4bool isExtreme = false;
1175  G4int size = fFacets.size();
1176  for (G4int i = 0; i < size; ++i)
1177  {
1178  G4VFacet &facet = *fFacets[i];
1179  if (facet.Intersect(p,v,true,dist,distFromSurface,normal))
1180  {
1181  if (distFromSurface > 0.0 && distFromSurface <= kCarToleranceHalf &&
1183  {
1184  // We are on a surface. Return zero.
1185  aConvex = (fExtremeFacets.find(&facet) != fExtremeFacets.end());
1186  // Normal(p, aNormalVector);
1187  // aNormalVector = facet.GetSurfaceNormal();
1188  aNormalVector = normal;
1189  return 0.0;
1190  }
1191  if (dist >= 0.0 && dist < minDist)
1192  {
1193  minDist = dist;
1194  minNormal = normal;
1195  isExtreme = (fExtremeFacets.find(&facet) != fExtremeFacets.end());
1196  }
1197  }
1198  }
1199  if (minDist < kInfinity)
1200  {
1201  aNormalVector = minNormal;
1202  aConvex = isExtreme;
1203  return minDist;
1204  }
1205  else
1206  {
1207  // No intersection found
1208  aConvex = false;
1209  Normal(p, aNormalVector);
1210  return 0.0;
1211  }
1212 }
1213 
1215 //
1217 DistanceToOutCandidates(const std::vector<G4int> &candidates,
1218  const G4ThreeVector &aPoint,
1219  const G4ThreeVector &direction,
1220  G4double &minDist, G4ThreeVector &minNormal,
1221  G4int &minCandidate ) const
1222 {
1223  G4int candidatesCount = candidates.size();
1224  G4double dist = 0.0;
1225  G4double distFromSurface = 0.0;
1227 
1228  for (G4int i = 0 ; i < candidatesCount; ++i)
1229  {
1230  G4int candidate = candidates[i];
1231  G4VFacet &facet = *fFacets[candidate];
1232  if (facet.Intersect(aPoint,direction,true,dist,distFromSurface,normal))
1233  {
1234  if (distFromSurface > 0.0 && distFromSurface <= kCarToleranceHalf
1235  && facet.Distance(aPoint,kCarTolerance) <= kCarToleranceHalf)
1236  {
1237  // We are on a surface
1238  //
1239  minDist = 0.0;
1240  minNormal = normal;
1241  minCandidate = candidate;
1242  break;
1243  }
1244  if (dist >= 0.0 && dist < minDist)
1245  {
1246  minDist = dist;
1247  minNormal = normal;
1248  minCandidate = candidate;
1249  }
1250  }
1251  }
1252 }
1253 
1255 //
1256 G4double
1258  const G4ThreeVector &aDirection,
1259  G4ThreeVector &aNormalVector,
1260  G4bool &aConvex,
1261  G4double aPstep) const
1262 {
1263  G4double minDistance;
1264 
1265  if (fVoxels.GetCountOfVoxels() > 1)
1266  {
1267  minDistance = kInfinity;
1268 
1269  G4ThreeVector currentPoint = aPoint;
1270  G4ThreeVector direction = aDirection.unit();
1271  G4double totalShift = 0;
1272  vector<G4int> curVoxel(3);
1273  if (!fVoxels.Contains(aPoint)) return 0;
1274 
1275  fVoxels.GetVoxel(curVoxel, currentPoint);
1276 
1277  G4double shiftBonus = kCarTolerance;
1278 
1279  const vector<G4int> *old = 0;
1280 
1281  G4int minCandidate = -1;
1282  do // Loop checking, 13.08.2015, G.Cosmo
1283  {
1284  const vector<G4int> &candidates = fVoxels.GetCandidates(curVoxel);
1285  if (old == &candidates)
1286  old++;
1287  if (old != &candidates && candidates.size())
1288  {
1289  DistanceToOutCandidates(candidates, aPoint, direction, minDistance,
1290  aNormalVector, minCandidate);
1291  if (minDistance <= totalShift) break;
1292  }
1293 
1294  G4double shift=fVoxels.DistanceToNext(currentPoint, direction, curVoxel);
1295  if (shift == kInfinity) break;
1296 
1297  totalShift += shift;
1298  if (minDistance <= totalShift) break;
1299 
1300  currentPoint += direction * (shift + shiftBonus);
1301 
1302  old = &candidates;
1303  }
1304  while (fVoxels.UpdateCurrentVoxel(currentPoint, direction, curVoxel));
1305 
1306  if (minCandidate < 0)
1307  {
1308  // No intersection found
1309  minDistance = 0;
1310  aConvex = false;
1311  Normal(aPoint, aNormalVector);
1312  }
1313  else
1314  {
1315  aConvex = (fExtremeFacets.find(fFacets[minCandidate])
1316  != fExtremeFacets.end());
1317  }
1318  }
1319  else
1320  {
1321  minDistance = DistanceToOutNoVoxels(aPoint, aDirection, aNormalVector,
1322  aConvex, aPstep);
1323  }
1324  return minDistance;
1325 }
1326 
1328 //
1330 DistanceToInCandidates(const std::vector<G4int> &candidates,
1331  const G4ThreeVector &aPoint,
1332  const G4ThreeVector &direction) const
1333 {
1334  G4int candidatesCount = candidates.size();
1335  G4double dist = 0.0;
1336  G4double distFromSurface = 0.0;
1338 
1339  G4double minDistance = kInfinity;
1340  for (G4int i = 0 ; i < candidatesCount; ++i)
1341  {
1342  G4int candidate = candidates[i];
1343  G4VFacet &facet = *fFacets[candidate];
1344  if (facet.Intersect(aPoint,direction,false,dist,distFromSurface,normal))
1345  {
1346  //
1347  // Set minDist to the new distance to current facet if distFromSurface is
1348  // in positive direction and point is not at surface. If the point is
1349  // within 0.5*kCarTolerance of the surface, then force distance to be
1350  // zero and leave member function immediately (for efficiency), as
1351  // proposed by & credit to Akira Okumura.
1352  //
1353  if ( (distFromSurface > kCarToleranceHalf)
1354  && (dist >= 0.0) && (dist < minDistance))
1355  {
1356  minDistance = dist;
1357  }
1358  else
1359  {
1360  if (-kCarToleranceHalf <= dist && dist <= kCarToleranceHalf)
1361  {
1362  return 0.0;
1363  }
1364  else if (distFromSurface > -kCarToleranceHalf
1365  && distFromSurface < kCarToleranceHalf)
1366  {
1367  minDistance = dist;
1368  }
1369  }
1370  }
1371  }
1372  return minDistance;
1373 }
1374 
1376 //
1377 G4double
1379  const G4ThreeVector &aDirection,
1380  G4double aPstep) const
1381 {
1382  G4double minDistance;
1383 
1384  if (fVoxels.GetCountOfVoxels() > 1)
1385  {
1386  minDistance = kInfinity;
1387  G4ThreeVector currentPoint = aPoint;
1388  G4ThreeVector direction = aDirection.unit();
1389  G4double shift = fVoxels.DistanceToFirst(currentPoint, direction);
1390  if (shift == kInfinity) return shift;
1391  G4double shiftBonus = kCarTolerance;
1392  if (shift)
1393  currentPoint += direction * (shift + shiftBonus);
1394  // if (!fVoxels.Contains(currentPoint)) return minDistance;
1395  G4double totalShift = shift;
1396 
1397  // G4SurfBits exclusion; // (1/*fVoxels.GetBitsPerSlice()*/);
1398  vector<G4int> curVoxel(3);
1399 
1400  fVoxels.GetVoxel(curVoxel, currentPoint);
1401  do // Loop checking, 13.08.2015, G.Cosmo
1402  {
1403  const vector<G4int> &candidates = fVoxels.GetCandidates(curVoxel);
1404  if (candidates.size())
1405  {
1406  G4double distance=DistanceToInCandidates(candidates, aPoint, direction);
1407  if (minDistance > distance) minDistance = distance;
1408  if (distance < totalShift) break;
1409  }
1410 
1411  shift = fVoxels.DistanceToNext(currentPoint, direction, curVoxel);
1412  if (shift == kInfinity /*|| shift == 0*/) break;
1413 
1414  totalShift += shift;
1415  if (minDistance < totalShift) break;
1416 
1417  currentPoint += direction * (shift + shiftBonus);
1418  }
1419  while (fVoxels.UpdateCurrentVoxel(currentPoint, direction, curVoxel));
1420  }
1421  else
1422  {
1423  minDistance = DistanceToInNoVoxels(aPoint, aDirection, aPstep);
1424  }
1425 
1426  return minDistance;
1427 }
1428 
1430 //
1431 G4bool
1432 G4TessellatedSolid::CompareSortedVoxel(const std::pair<G4int, G4double> &l,
1433  const std::pair<G4int, G4double> &r)
1434 {
1435  return l.second < r.second;
1436 }
1437 
1439 //
1440 G4double
1442  G4bool simple,
1443  G4VFacet * &minFacet) const
1444 {
1445  G4double minDist = kInfinity;
1446 
1447  G4int size = fVoxels.GetVoxelBoxesSize();
1448  vector<pair<G4int, G4double> > voxelsSorted(size);
1449 
1450  pair<G4int, G4double> info;
1451 
1452  for (G4int i = 0; i < size; ++i)
1453  {
1454  const G4VoxelBox &voxelBox = fVoxels.GetVoxelBox(i);
1455 
1456  G4ThreeVector pointShifted = p - voxelBox.pos;
1457  G4double safety = fVoxels.MinDistanceToBox(pointShifted, voxelBox.hlen);
1458  info.first = i;
1459  info.second = safety;
1460  voxelsSorted[i] = info;
1461  }
1462 
1463  std::sort(voxelsSorted.begin(), voxelsSorted.end(),
1465 
1466  for (G4int i = 0; i < size; ++i)
1467  {
1468  const pair<G4int,G4double> &inf = voxelsSorted[i];
1469  G4double dist = inf.second;
1470  if (dist > minDist) break;
1471 
1472  const vector<G4int> &candidates = fVoxels.GetVoxelBoxCandidates(inf.first);
1473  G4int csize = candidates.size();
1474  for (G4int j = 0; j < csize; ++j)
1475  {
1476  G4int candidate = candidates[j];
1477  G4VFacet &facet = *fFacets[candidate];
1478  dist = simple ? facet.Distance(p,minDist)
1479  : facet.Distance(p,minDist,false);
1480  if (dist < minDist)
1481  {
1482  minDist = dist;
1483  minFacet = &facet;
1484  }
1485  }
1486  }
1487  return minDist;
1488 }
1489 
1491 //
1493  G4bool aAccurate) const
1494 {
1495 #if G4SPECSDEBUG
1496  if ( Inside(p) == kInside )
1497  {
1498  std::ostringstream message;
1499  G4int oldprc = message.precision(16) ;
1500  message << "Point p is already inside!?" << G4endl
1501  << "Position:" << G4endl << G4endl
1502  << "p.x() = " << p.x()/mm << " mm" << G4endl
1503  << "p.y() = " << p.y()/mm << " mm" << G4endl
1504  << "p.z() = " << p.z()/mm << " mm" << G4endl
1505  << "DistanceToOut(p) == " << DistanceToOut(p);
1506  message.precision(oldprc) ;
1507  G4Exception("G4TriangularFacet::DistanceToIn(p)",
1508  "GeomSolids1002", JustWarning, message);
1509  }
1510 #endif
1511 
1512  G4double minDist;
1513 
1514  if (fVoxels.GetCountOfVoxels() > 1)
1515  {
1516  if (!aAccurate)
1517  return fVoxels.DistanceToBoundingBox(p);
1518 
1519  if (!OutsideOfExtent(p, kCarTolerance))
1520  {
1521  vector<G4int> startingVoxel(3);
1522  fVoxels.GetVoxel(startingVoxel, p);
1523  const vector<G4int> &candidates = fVoxels.GetCandidates(startingVoxel);
1524  if (candidates.size() == 0 && fInsides.GetNbits())
1525  {
1526  G4int index = fVoxels.GetPointIndex(p);
1527  if (fInsides[index]) return 0.;
1528  }
1529  }
1530 
1531  G4VFacet *facet;
1532  minDist = MinDistanceFacet(p, true, facet);
1533  }
1534  else
1535  {
1536  minDist = kInfinity;
1537  G4int size = fFacets.size();
1538  for (G4int i = 0; i < size; ++i)
1539  {
1540  G4VFacet &facet = *fFacets[i];
1541  G4double dist = facet.Distance(p,minDist);
1542  if (dist < minDist) minDist = dist;
1543  }
1544  }
1545  return minDist;
1546 }
1547 
1549 //
1550 G4double
1552 {
1553 #if G4SPECSDEBUG
1554  if ( Inside(p) == kOutside )
1555  {
1556  std::ostringstream message;
1557  G4int oldprc = message.precision(16) ;
1558  message << "Point p is already outside!?" << G4endl
1559  << "Position:" << G4endl << G4endl
1560  << "p.x() = " << p.x()/mm << " mm" << G4endl
1561  << "p.y() = " << p.y()/mm << " mm" << G4endl
1562  << "p.z() = " << p.z()/mm << " mm" << G4endl
1563  << "DistanceToIn(p) == " << DistanceToIn(p);
1564  message.precision(oldprc) ;
1565  G4Exception("G4TriangularFacet::DistanceToOut(p)",
1566  "GeomSolids1002", JustWarning, message);
1567  }
1568 #endif
1569 
1570  G4double minDist;
1571 
1572  if (OutsideOfExtent(p, kCarTolerance)) return 0.0;
1573 
1574  if (fVoxels.GetCountOfVoxels() > 1)
1575  {
1576  G4VFacet *facet;
1577  minDist = MinDistanceFacet(p, true, facet);
1578  }
1579  else
1580  {
1581  minDist = kInfinity;
1582  G4double dist = 0.0;
1583  G4int size = fFacets.size();
1584  for (G4int i = 0; i < size; ++i)
1585  {
1586  G4VFacet &facet = *fFacets[i];
1587  dist = facet.Distance(p,minDist);
1588  if (dist < minDist) minDist = dist;
1589  }
1590  }
1591  return minDist;
1592 }
1593 
1595 //
1596 // G4GeometryType GetEntityType() const;
1597 //
1598 // Provide identification of the class of an object
1599 //
1601 {
1602  return fGeometryType;
1603 }
1604 
1606 //
1607 std::ostream &G4TessellatedSolid::StreamInfo(std::ostream &os) const
1608 {
1609  os << G4endl;
1610  os << "Solid name = " << GetName() << G4endl;
1611  os << "Geometry Type = " << fGeometryType << G4endl;
1612  os << "Number of facets = " << fFacets.size() << G4endl;
1613 
1614  G4int size = fFacets.size();
1615  for (G4int i = 0; i < size; ++i)
1616  {
1617  os << "FACET # = " << i + 1 << G4endl;
1618  G4VFacet &facet = *fFacets[i];
1619  facet.StreamInfo(os);
1620  }
1621  os << G4endl;
1622 
1623  return os;
1624 }
1625 
1627 //
1628 // Make a clone of the object
1629 //
1631 {
1632  return new G4TessellatedSolid(*this);
1633 }
1634 
1636 //
1637 // EInside G4TessellatedSolid::Inside (const G4ThreeVector &p) const
1638 //
1639 // This method must return:
1640 // * kOutside if the point at offset p is outside the shape
1641 // boundaries plus kCarTolerance/2,
1642 // * kSurface if the point is <= kCarTolerance/2 from a surface, or
1643 // * kInside otherwise.
1644 //
1646 {
1647  EInside location;
1648 
1649  if (fVoxels.GetCountOfVoxels() > 1)
1650  {
1651  location = InsideVoxels(aPoint);
1652  }
1653  else
1654  {
1655  location = InsideNoVoxels(aPoint);
1656  }
1657  return location;
1658 }
1659 
1661 //
1663 {
1664  G4ThreeVector n;
1665  Normal(p, n);
1666  return n;
1667 }
1668 
1670 //
1671 // G4double DistanceToIn(const G4ThreeVector& p)
1672 //
1673 // Calculate distance to nearest surface of shape from an outside point p. The
1674 // distance can be an underestimate.
1675 //
1677 {
1678  return SafetyFromOutside(p,false);
1679 }
1680 
1682 //
1684  const G4ThreeVector& v)const
1685 {
1686  G4double dist = DistanceToInCore(p,v,kInfinity);
1687 #ifdef G4SPECSDEBUG
1688  if (dist < kInfinity)
1689  {
1690  if (Inside(p + dist*v) != kSurface)
1691  {
1692  std::ostringstream message;
1693  message << "Invalid response from facet in solid '" << GetName() << "',"
1694  << G4endl
1695  << "at point: " << p << "and direction: " << v;
1696  G4Exception("G4TessellatedSolid::DistanceToIn(p,v)",
1697  "GeomSolids1002", JustWarning, message);
1698  }
1699  }
1700 #endif
1701  return dist;
1702 }
1703 
1705 //
1706 // G4double DistanceToOut(const G4ThreeVector& p)
1707 //
1708 // Calculate distance to nearest surface of shape from an inside
1709 // point. The distance can be an underestimate.
1710 //
1712 {
1713  return SafetyFromInside(p,false);
1714 }
1715 
1717 //
1718 // G4double DistanceToOut(const G4ThreeVector& p, const G4ThreeVector& v,
1719 // const G4bool calcNorm=false,
1720 // G4bool *validNorm=0, G4ThreeVector *n=0);
1721 //
1722 // Return distance along the normalised vector v to the shape, from a
1723 // point at an offset p inside or on the surface of the
1724 // shape. Intersections with surfaces, when the point is not greater
1725 // than kCarTolerance/2 from a surface, must be ignored.
1726 // If calcNorm is true, then it must also set validNorm to either
1727 // * true, if the solid lies entirely behind or on the exiting
1728 // surface. Then it must set n to the outwards normal vector
1729 // (the Magnitude of the vector is not defined).
1730 // * false, if the solid does not lie entirely behind or on the
1731 // exiting surface.
1732 // If calcNorm is false, then validNorm and n are unused.
1733 //
1735  const G4ThreeVector& v,
1736  const G4bool calcNorm,
1737  G4bool *validNorm,
1738  G4ThreeVector *norm) const
1739 {
1740  G4ThreeVector n;
1741  G4bool valid;
1742 
1743  G4double dist = DistanceToOutCore(p, v, n, valid);
1744  if (calcNorm)
1745  {
1746  *norm = n;
1747  *validNorm = valid;
1748  }
1749 #ifdef G4SPECSDEBUG
1750  if (dist < kInfinity)
1751  {
1752  if (Inside(p + dist*v) != kSurface)
1753  {
1754  std::ostringstream message;
1755  message << "Invalid response from facet in solid '" << GetName() << "',"
1756  << G4endl
1757  << "at point: " << p << "and direction: " << v;
1758  G4Exception("G4TessellatedSolid::DistanceToOut(p,v,..)",
1759  "GeomSolids1002", JustWarning, message);
1760  }
1761  }
1762 #endif
1763  return dist;
1764 }
1765 
1767 //
1769 {
1770  scene.AddSolid (*this);
1771 }
1772 
1774 //
1776 {
1777  G4int nVertices = fVertexList.size();
1778  G4int nFacets = fFacets.size();
1779  G4PolyhedronArbitrary *polyhedron =
1780  new G4PolyhedronArbitrary (nVertices, nFacets);
1781  for (G4ThreeVectorList::const_iterator v= fVertexList.begin();
1782  v!=fVertexList.end(); ++v)
1783  {
1784  polyhedron->AddVertex(*v);
1785  }
1786 
1787  G4int size = fFacets.size();
1788  for (G4int i = 0; i < size; ++i)
1789  {
1790  G4VFacet* facet = fFacets[i];
1791  G4int v[4];
1792  G4int n = facet->GetNumberOfVertices();
1793  if (n > 4) n = 4;
1794  else if (n == 3) v[3] = 0;
1795  for (G4int j=0; j<n; ++j)
1796  {
1797  G4int k = facet->GetVertexIndex(j);
1798  v[j] = k+1;
1799  }
1800  polyhedron->AddFacet(v[0],v[1],v[2],v[3]);
1801  }
1802  polyhedron->SetReferences();
1803 
1804  return (G4Polyhedron*) polyhedron;
1805 }
1806 
1808 //
1809 // GetPolyhedron
1810 //
1812 {
1813  if (!fpPolyhedron ||
1817  {
1818  G4AutoLock l(&polyhedronMutex);
1819  delete fpPolyhedron;
1821  fRebuildPolyhedron = false;
1822  l.unlock();
1823  }
1824  return fpPolyhedron;
1825 }
1826 
1828 //
1829 // Get bounding box
1830 //
1832  G4ThreeVector& pMax) const
1833 {
1834  pMin = fMinExtent;
1835  pMax = fMaxExtent;
1836 
1837  // Check correctness of the bounding box
1838  //
1839  if (pMin.x() >= pMax.x() || pMin.y() >= pMax.y() || pMin.z() >= pMax.z())
1840  {
1841  std::ostringstream message;
1842  message << "Bad bounding box (min >= max) for solid: "
1843  << GetName() << " !"
1844  << "\npMin = " << pMin
1845  << "\npMax = " << pMax;
1846  G4Exception("G4TessellatedSolid::BoundingLimits()",
1847  "GeomMgt0001", JustWarning, message);
1848  DumpInfo();
1849  }
1850 }
1851 
1853 //
1854 // Calculate extent under transform and specified limit
1855 //
1856 G4bool
1858  const G4VoxelLimits& pVoxelLimit,
1859  const G4AffineTransform& pTransform,
1860  G4double& pMin, G4double& pMax) const
1861 {
1862  G4ThreeVector bmin, bmax;
1863  G4bool exist;
1864 
1865  // Check bounding box (bbox)
1866  //
1867  BoundingLimits(bmin,bmax);
1868  G4BoundingEnvelope bbox(bmin,bmax);
1869 #ifdef G4BBOX_EXTENT
1870  if (true) return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
1871 #endif
1872  if (bbox.BoundingBoxVsVoxelLimits(pAxis,pVoxelLimit,pTransform,pMin,pMax))
1873  {
1874  return exist = (pMin < pMax) ? true : false;
1875  }
1876 
1877  // The extent is calculated as cumulative extent of the pyramids
1878  // formed by facets and the center of the bounding box.
1879  //
1880  G4double eminlim = pVoxelLimit.GetMinExtent(pAxis);
1881  G4double emaxlim = pVoxelLimit.GetMaxExtent(pAxis);
1882 
1884  G4ThreeVectorList apex(1);
1885  std::vector<const G4ThreeVectorList *> pyramid(2);
1886  pyramid[0] = &base;
1887  pyramid[1] = &apex;
1888  apex[0] = (bmin+bmax)*0.5;
1889 
1890  // main loop along facets
1891  pMin = kInfinity;
1892  pMax = -kInfinity;
1893  for (G4int i=0; i<GetNumberOfFacets(); ++i)
1894  {
1895  G4VFacet* facet = GetFacet(i);
1896  if (std::abs((facet->GetSurfaceNormal()).dot(facet->GetVertex(0)-apex[0]))
1897  < kCarToleranceHalf) continue;
1898 
1899  G4int nv = facet->GetNumberOfVertices();
1900  base.resize(nv);
1901  for (G4int k=0; k<nv; ++k) { base[k] = facet->GetVertex(k); }
1902 
1903  G4double emin,emax;
1904  G4BoundingEnvelope benv(pyramid);
1905  if (!benv.CalculateExtent(pAxis,pVoxelLimit,pTransform,emin,emax)) continue;
1906  if (emin < pMin) pMin = emin;
1907  if (emax > pMax) pMax = emax;
1908  if (eminlim > pMin && emaxlim < pMax) break; // max possible extent
1909  }
1910  return (pMin < pMax);
1911 }
1912 
1914 //
1916 {
1917  return fMinExtent.x();
1918 }
1919 
1921 //
1923 {
1924  return fMaxExtent.x();
1925 }
1926 
1928 //
1930 {
1931  return fMinExtent.y();
1932 }
1933 
1935 //
1937 {
1938  return fMaxExtent.y();
1939 }
1940 
1942 //
1944 {
1945  return fMinExtent.z();
1946 }
1947 
1949 //
1951 {
1952  return fMaxExtent.z();
1953 }
1954 
1956 //
1958 {
1959  return G4VisExtent (fMinExtent.x(), fMaxExtent.x(),
1960  fMinExtent.y(), fMaxExtent.y(),
1961  fMinExtent.z(), fMaxExtent.z());
1962 }
1963 
1965 //
1967 {
1968  if (fCubicVolume != 0.) return fCubicVolume;
1969 
1970  // For explanation of the following algorithm see:
1971  // https://en.wikipedia.org/wiki/Polyhedron#Volume
1972  // http://wwwf.imperial.ac.uk/~rn/centroid.pdf
1973 
1974  G4int size = fFacets.size();
1975  for (G4int i = 0; i < size; ++i)
1976  {
1977  G4VFacet &facet = *fFacets[i];
1978  G4double area = facet.GetArea();
1979  G4ThreeVector unit_normal = facet.GetSurfaceNormal();
1980  fCubicVolume += area * (facet.GetVertex(0).dot(unit_normal));
1981  }
1982  fCubicVolume /= 3.;
1983  return fCubicVolume;
1984 }
1985 
1987 //
1989 {
1990  if (fSurfaceArea != 0.) return fSurfaceArea;
1991 
1992  G4int size = fFacets.size();
1993  for (G4int i = 0; i < size; ++i)
1994  {
1995  G4VFacet &facet = *fFacets[i];
1996  fSurfaceArea += facet.GetArea();
1997  }
1998  return fSurfaceArea;
1999 }
2000 
2002 //
2004 {
2005  // Select randomly a facet and return a random point on it
2006 
2007  G4int i = (G4int) G4RandFlat::shoot(0., fFacets.size());
2008  return fFacets[i]->GetPointOnFace();
2009 }
2010 
2012 //
2013 // SetRandomVectorSet
2014 //
2015 // This is a set of predefined random vectors (if that isn't a contradition
2016 // in terms!) used to generate rays from a user-defined point. The member
2017 // function Inside uses these to determine whether the point is inside or
2018 // outside of the tessellated solid. All vectors should be unit vectors.
2019 //
2021 {
2022  fRandir.resize(20);
2023  fRandir[0] =
2024  G4ThreeVector(-0.9577428892113370, 0.2732676269591740, 0.0897405271949221);
2025  fRandir[1] =
2026  G4ThreeVector(-0.8331264504940770,-0.5162067214954600,-0.1985722492445700);
2027  fRandir[2] =
2028  G4ThreeVector(-0.1516671651108820, 0.9666292616127460, 0.2064580868390110);
2029  fRandir[3] =
2030  G4ThreeVector( 0.6570250350323190,-0.6944539025883300, 0.2933460081893360);
2031  fRandir[4] =
2032  G4ThreeVector(-0.4820456281280320,-0.6331060000098690,-0.6056474264406270);
2033  fRandir[5] =
2034  G4ThreeVector( 0.7629032554236800 , 0.1016854697539910,-0.6384658864065180);
2035  fRandir[6] =
2036  G4ThreeVector( 0.7689540409061150, 0.5034929891988220, 0.3939600142169160);
2037  fRandir[7] =
2038  G4ThreeVector( 0.5765188359255740, 0.5997271636278330,-0.5549354566343150);
2039  fRandir[8] =
2040  G4ThreeVector( 0.6660632777862070,-0.6362809868288380, 0.3892379937580790);
2041  fRandir[9] =
2042  G4ThreeVector( 0.3824415020414780, 0.6541792713761380,-0.6525243125110690);
2043  fRandir[10] =
2044  G4ThreeVector(-0.5107726564526760, 0.6020905056811610, 0.6136760679616570);
2045  fRandir[11] =
2046  G4ThreeVector( 0.7459135439578050, 0.6618796061649330, 0.0743530220183488);
2047  fRandir[12] =
2048  G4ThreeVector( 0.1536405855311580, 0.8117477913978260,-0.5634359711967240);
2049  fRandir[13] =
2050  G4ThreeVector( 0.0744395301705579,-0.8707110101772920,-0.4861286795736560);
2051  fRandir[14] =
2052  G4ThreeVector(-0.1665874645185400, 0.6018553940549240,-0.7810369397872780);
2053  fRandir[15] =
2054  G4ThreeVector( 0.7766902003633100, 0.6014617505959970,-0.1870724331097450);
2055  fRandir[16] =
2056  G4ThreeVector(-0.8710128685847430,-0.1434320216603030,-0.4698551243971010);
2057  fRandir[17] =
2058  G4ThreeVector( 0.8901082092766820,-0.4388411398893870, 0.1229871120030100);
2059  fRandir[18] =
2060  G4ThreeVector(-0.6430417431544370,-0.3295938228697690, 0.6912779675984150);
2061  fRandir[19] =
2062  G4ThreeVector( 0.6331124368380410, 0.6306211461665000, 0.4488714875425340);
2063 
2064  fMaxTries = 20;
2065 }
2066 
2068 //
2070 {
2071  G4int base = sizeof(*this);
2072  base += fVertexList.capacity() * sizeof(G4ThreeVector);
2073  base += fRandir.capacity() * sizeof(G4ThreeVector);
2074 
2075  G4int limit = fFacets.size();
2076  for (G4int i = 0; i < limit; i++)
2077  {
2078  G4VFacet &facet = *fFacets[i];
2079  base += facet.AllocatedMemory();
2080  }
2081 
2082  std::set<G4VFacet *>::const_iterator beg, end, it;
2083  beg = fExtremeFacets.begin();
2084  end = fExtremeFacets.end();
2085  for (it = beg; it != end; it++)
2086  {
2087  G4VFacet &facet = *(*it);
2088  base += facet.AllocatedMemory();
2089  }
2090  return base;
2091 }
2092 
2094 //
2096 {
2098  G4int sizeInsides = fInsides.GetNbytes();
2099  G4int sizeVoxels = fVoxels.AllocatedMemory();
2100  size += sizeInsides + sizeVoxels;
2101  return size;
2102 }
2103 
2104 #endif
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimits, const G4Transform3D &pTransform3D, G4double &pMin, G4double &pMax) const
G4int GetPointIndex(const G4ThreeVector &p) const
void CopyObjects(const G4TessellatedSolid &s)
G4double GetMinZExtent() const
virtual G4int GetVertexIndex(G4int i) const =0
void set(double x, double y, double z)
const XML_Char XML_Encoding * info
Definition: expat.h:530
T max(const T t1, const T t2)
brief Return the largest of the two arguments
virtual G4ThreeVector GetSurfaceNormal() const =0
const XML_Char * name
Definition: expat.h:151
const G4SurfBits & Empty() const
G4bool GetSolidClosed() const
G4bool IsInside(const G4ThreeVector &p) const
Definition: G4VFacet.cc:114
CLHEP::Hep3Vector G4ThreeVector
const std::vector< G4int > & GetVoxelBoxCandidates(G4int i) const
void ResetBitNumber(unsigned int bitnumber)
Definition: G4SurfBits.hh:161
void Voxelize(std::vector< G4VSolid * > &solids, std::vector< G4Transform3D > &transforms)
Definition: G4Voxelizer.cc:724
G4double GetMaxExtent(const EAxis pAxis) const
std::vector< ExP01TrackerHit * > a
Definition: ExP01Classes.hh:33
unsigned int GetNbits() const
Definition: G4SurfBits.hh:101
G4bool Contains(const G4ThreeVector &point) const
virtual G4double GetArea() const =0
static const G4double pos
G4double GetMaxXExtent() const
virtual void AddSolid(const G4Box &)=0
static const G4double kInfinity
Definition: geomdefs.hh:42
G4bool IsEmpty(G4int index) const
void AddFacet(const G4int iv1, const G4int iv2, const G4int iv3, const G4int iv4=0)
void AddVertex(const G4ThreeVector &v)
virtual G4VFacet * GetClone()=0
virtual G4VisExtent GetExtent() const
static constexpr double mm
Definition: G4SIunits.hh:115
virtual void DescribeYourselfTo(G4VGraphicsScene &scene) const
G4TessellatedSolid & operator=(const G4TessellatedSolid &right)
virtual G4VSolid * Clone() const
#define G4endl
Definition: G4ios.hh:61
std::set< G4VFacet * > fExtremeFacets
const char * p
Definition: xmltok.h:285
unsigned int GetNbytes() const
Definition: G4SurfBits.hh:102
std::ostream & StreamInfo(std::ostream &os) const
Definition: G4VFacet.cc:98
void message(RunManager *runmanager)
Definition: ts_scorers.cc:72
const std::vector< G4int > & GetCandidates(std::vector< G4int > &curVoxel) const
EInside InsideNoVoxels(const G4ThreeVector &p) const
const std::vector< G4double > & GetBoundary(G4int index) const
double z() const
static double normal(HepRandomEngine *eptr)
Definition: RandPoisson.cc:77
double dot(const Hep3Vector &) const
virtual G4Polyhedron * GetPolyhedron() const
virtual std::ostream & StreamInfo(std::ostream &os) const
static const G4double emax
long long GetCountOfVoxels() const
virtual void SetVertexIndex(G4int i, G4int j)=0
void BoundingLimits(G4ThreeVector &pMin, G4ThreeVector &pMax) const
virtual G4ThreeVector GetVertex(G4int i) const =0
virtual G4double Distance(const G4ThreeVector &, G4double)=0
G4ThreeVector hlen
Definition: G4Voxelizer.hh:58
virtual EInside Inside(const G4ThreeVector &p) const
void setX(double)
const XML_Char int const XML_Char int const XML_Char * base
Definition: expat.h:331
void Clear()
Definition: G4SurfBits.cc:92
void SetSolidClosed(const G4bool t)
G4bool AddFacet(G4VFacet *aFacet)
virtual G4double GetCubicVolume()
G4VSolid & operator=(const G4VSolid &rhs)
Definition: G4VSolid.cc:110
G4double GetMinXExtent() const
void SetMaxVoxels(G4int max)
G4bool BoundingBoxVsVoxelLimits(const EAxis pAxis, const G4VoxelLimits &pVoxelLimits, const G4Transform3D &pTransform3D, G4double &pMin, G4double &pMax) const
virtual G4double SafetyFromOutside(const G4ThreeVector &p, G4bool aAccurate=false) const
G4double DistanceToInCandidates(const std::vector< G4int > &candidates, const G4ThreeVector &aPoint, const G4ThreeVector &aDirection) const
G4double DistanceToFirst(const G4ThreeVector &point, const G4ThreeVector &direction) const
double G4double
Definition: G4Types.hh:76
bool G4bool
Definition: G4Types.hh:79
std::vector< G4ThreeVector > G4ThreeVectorList
#define G4MUTEX_INITIALIZER
Definition: G4Threading.hh:88
G4double GetMaxZExtent() const
G4double DistanceToOutNoVoxels(const G4ThreeVector &p, const G4ThreeVector &v, G4ThreeVector &aNormalVector, G4bool &aConvex, G4double aPstep=kInfinity) const
static G4bool CompareSortedVoxel(const std::pair< G4int, G4double > &l, const std::pair< G4int, G4double > &r)
virtual G4double SafetyFromInside(const G4ThreeVector &p, G4bool aAccurate=false) const
G4int GetMaxVoxels(G4ThreeVector &ratioOfReduction)
const XML_Char int const XML_Char * value
Definition: expat.h:331
G4double GetMinExtent(const EAxis pAxis) const
virtual G4double GetSurfaceArea()
G4double DistanceToOutCore(const G4ThreeVector &p, const G4ThreeVector &v, G4ThreeVector &aNormalVector, G4bool &aConvex, G4double aPstep=kInfinity) const
virtual G4GeometryType GetEntityType() const
virtual G4double DistanceToOut(const G4ThreeVector &p) const
void setZ(double)
G4int GetNumberOfFacets() const
G4double kCarTolerance
Definition: G4VSolid.hh:307
virtual G4bool IsDefined() const =0
G4int GetVoxelBoxesSize() const
virtual G4int GetNumberOfVertices() const =0
static G4double MinDistanceToBox(const G4ThreeVector &aPoint, const G4ThreeVector &f)
virtual G4Polyhedron * CreatePolyhedron() const
ThreeVector shoot(const G4int Ap, const G4int Af)
G4ThreeVector pos
Definition: G4Voxelizer.hh:59
G4bool OutsideOfExtent(const G4ThreeVector &p, G4double tolerance=0) const
Hep3Vector unit() const
static G4int GetNumberOfRotationSteps()
G4int AllocatedMemory()
virtual G4ThreeVector GetPointOnSurface() const
G4double GetMaxYExtent() const
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
Definition: G4Exception.hh:65
virtual G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const
G4double DistanceToNext(const G4ThreeVector &point, const G4ThreeVector &direction, std::vector< G4int > &curVoxel) const
std::vector< G4ThreeVector > fRandir
G4int GetNumberOfRotationStepsAtTimeOfCreation() const
int G4int
Definition: G4Types.hh:78
EInside
Definition: geomdefs.hh:58
std::vector< G4VFacet * > fFacets
EAxis
Definition: geomdefs.hh:54
G4String GetName() const
void DumpInfo() const
Float_t norm
virtual G4ThreeVector GetCircumcentre() const =0
G4GLOB_DLL std::ostream G4cout
double x() const
EInside InsideVoxels(const G4ThreeVector &aPoint) const
virtual G4ThreeVector SurfaceNormal(const G4ThreeVector &p) const
G4TessellatedSolid & operator+=(const G4TessellatedSolid &right)
virtual G4bool Intersect(const G4ThreeVector &, const G4ThreeVector &, const G4bool, G4double &, G4double &, G4ThreeVector &)=0
G4bool UpdateCurrentVoxel(const G4ThreeVector &point, const G4ThreeVector &direction, std::vector< G4int > &curVoxel) const
Char_t n[5]
void SetBitNumber(unsigned int bitnumber, G4bool value=true)
Definition: G4SurfBits.hh:123
G4double DistanceToBoundingBox(const G4ThreeVector &point) const
G4double GetMinYExtent() const
virtual G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimit, const G4AffineTransform &pTransform, G4double &pMin, G4double &pMax) const
double y() const
G4double DistanceToInNoVoxels(const G4ThreeVector &p, const G4ThreeVector &v, G4double aPstep=kInfinity) const
void GetVoxel(std::vector< G4int > &curVoxel, const G4ThreeVector &point) const
virtual G4bool Normal(const G4ThreeVector &p, G4ThreeVector &n) const
G4int GetVoxelsIndex(G4int x, G4int y, G4int z) const
virtual void SetVertices(std::vector< G4ThreeVector > *vertices)=0
const G4VoxelBox & GetVoxelBox(G4int i) const
std::vector< G4ThreeVector > fVertexList
G4double DistanceToInCore(const G4ThreeVector &p, const G4ThreeVector &v, G4double aPstep=kInfinity) const
virtual G4int AllocatedMemory()=0
void DistanceToOutCandidates(const std::vector< G4int > &candidates, const G4ThreeVector &aPoint, const G4ThreeVector &direction, G4double &minDist, G4ThreeVector &minNormal, G4int &minCandidate) const
G4double MinDistanceFacet(const G4ThreeVector &p, G4bool simple, G4VFacet *&facet) const
void setY(double)
G4int SetAllUsingStack(const std::vector< G4int > &voxel, const std::vector< G4int > &max, G4bool status, G4SurfBits &checked)
G4GeometryType fGeometryType
G4Polyhedron * fpPolyhedron
std::mutex G4Mutex
Definition: G4Threading.hh:84
std::set< G4VertexInfo, G4VertexComparator > fFacetList
G4VFacet * GetFacet(G4int i) const