59 fTransformObjs.clear();
71 fSolids.push_back(&solid);
72 fTransformObjs.push_back(trans);
84 :
G4VSolid(rhs), fCubicVolume(rhs.fCubicVolume),
85 fSurfaceArea(rhs.fSurfaceArea),
86 kRadTolerance(rhs.kRadTolerance), fAccurate(rhs.fAccurate)
124 G4int inside = 0, generated;
126 d = (extentMax - extentMin) / 2.;
127 p = (extentMax + extentMin) / 2.;
130 for (generated = 0; generated < 10000; ++generated)
135 length.
z()*rvec.
z());
136 if (
Inside(point) != EInside::kOutside) ++inside;
138 G4double vbox = (2 * d.
x()) * (2 * d.
y()) * (2 * d.
z());
139 fCubicVolume = inside * vbox / generated;
153 G4int numNodes = fSolids.size();
154 for (
G4int i = 0 ; i < numNodes ; ++i)
159 localPoint = GetLocalPoint(transform, aPoint);
160 localDirection = GetLocalVector(transform, direction);
163 if (minDistance > distance) minDistance = distance;
171 std::vector<G4int>& candidates,
174 G4int candidatesCount = candidates.size();
178 for (
G4int i = 0 ; i < candidatesCount; ++i)
180 G4int candidate = candidates[i];
181 G4VSolid& solid = *fSolids[candidate];
184 localPoint = GetLocalPoint(transform, aPoint);
185 localDirection = GetLocalVector(transform, direction);
187 if (minDistance > distance) minDistance = distance;
189 if (minDistance == 0)
break;
211 if (shift == kInfinity)
return shift;
214 if (shift) currentPoint += direction * shift;
217 std::vector<G4int> candidates, curVoxel(3);
218 fVoxels.
GetVoxel(curVoxel, currentPoint);
225 G4double distance = DistanceToInCandidates(aPoint, direction,
226 candidates, exclusion);
227 if (minDistance > distance) minDistance = distance;
228 if (distance < shift)
break;
233 while (minDistance > shift);
253 G4int ignoredSolid = -1;
257 G4int numNodes = fSolids.size();
258 for (
G4int i = 0; i < numNodes; ++i)
260 if (i != ignoredSolid)
264 localPoint = GetLocalPoint(transform, currentPoint);
265 localDirection = GetLocalVector(transform, direction);
267 if (location != EInside::kOutside)
271 if (distance < kInfinity)
273 if (resultDistToOut == kInfinity) resultDistToOut = 0;
276 currentPoint = GetGlobalPoint(transform, localPoint
277 + distance*localDirection);
278 resultDistToOut += distance;
286 return resultDistToOut;
319 std::vector<G4int> candidates;
321 G4int numNodes = 2*fSolids.size();
338 G4int maxCandidate = 0;
341 G4int limit = candidates.size();
342 for (
G4int i = 0 ; i < limit ; ++i)
344 G4int candidate = candidates[i];
348 G4VSolid& solid = *fSolids[candidate];
353 localPoint = GetLocalPoint(transform, currentPoint);
360 if (solid.
Inside(localPoint) != EInside::kOutside)
364 localDirection = GetLocalVector(transform, direction);
368 false, 0, &localNormal);
369 if (maxDistance < shift)
372 maxCandidate = candidate;
373 maxNormal = localNormal;
380 const G4Transform3D& transform = fTransformObjs[maxCandidate];
383 if (aNormal) *aNormal = GetGlobalVector(transform, maxNormal);
385 distance += maxDistance;
386 currentPoint += maxDistance * direction;
387 if(maxDistance == 0.) ++count;
391 EInside location = InsideWithExclusion(currentPoint, &exclusion);
398 if (location == EInside::kOutside)
415 while ((notOutside) && (count < numNodes));
437 EInside location = EInside::kOutside;
439 std::vector<G4int> candidates;
440 std::vector<G4MultiUnionSurface> surfaces;
450 for (
G4int i = 0 ; i < limit ; ++i)
452 G4int candidate = candidates[i];
453 G4VSolid& solid = *fSolids[candidate];
458 localPoint = GetLocalPoint(transform, aPoint);
459 location = solid.
Inside(localPoint);
460 if (location == EInside::kInside)
return EInside::kInside;
461 else if (location == EInside::kSurface)
463 G4MultiUnionSurface surface;
464 surface.point = localPoint;
465 surface.solid = &solid;
466 surfaces.push_back(surface);
475 G4int size = surfaces.size();
476 for (
G4int i = 0; i < size - 1; ++i)
478 G4MultiUnionSurface& left = surfaces[i];
479 for (
G4int j = i + 1; j < size; ++j)
481 G4MultiUnionSurface& right = surfaces[j];
483 n = left.solid->SurfaceNormal(left.point);
484 n2 = right.solid->SurfaceNormal(right.point);
485 if ((n + n2).mag2() < 1000 * kRadTolerance)
486 return EInside::kInside;
490 location = size ? EInside::kSurface : EInside::kOutside;
511 EInside location = InsideWithExclusion(aPoint);
519 EInside location = EInside::kOutside;
520 G4int countSurface = 0;
522 G4int numNodes = fSolids.size();
523 for (
G4int i = 0 ; i < numNodes ; ++i)
530 localPoint = GetLocalPoint(transform, aPoint);
532 location = solid.
Inside(localPoint);
534 if (location == EInside::kSurface)
537 if (location == EInside::kInside)
return EInside::kInside;
539 if (countSurface != 0)
return EInside::kSurface;
540 return EInside::kOutside;
549 G4int numNodes = fSolids.size();
550 for (
G4int i = 0 ; i < numNodes ; ++i)
556 TransformLimits(min, max, transform);
645 std::vector<G4int> candidates;
657 G4int limit = candidates.size();
658 for (
G4int i = 0 ; i < limit ; ++i)
660 G4int candidate = candidates[i];
665 localPoint = GetLocalPoint(transform, aPoint);
666 G4VSolid& solid = *fSolids[candidate];
669 if (location == EInside::kSurface)
672 normal = GetGlobalVector(transform, solid.
SurfaceNormal(localPoint));
673 return normal.
unit();
678 G4double s = (location == EInside::kInside)
691 localPoint = GetLocalPoint(transform, aPoint);
693 normal = GetGlobalVector(transform, solid.
SurfaceNormal(localPoint));
694 return normal.
unit();
701 node = SafetyFromOutsideNumberNode(aPoint, safety);
705 localPoint = GetLocalPoint(transform, aPoint);
709 normal = GetGlobalVector(transform, solid.
SurfaceNormal(localPoint));
711 return normal.
unit();
723 std::vector<G4int> candidates;
731 G4int limit = candidates.size();
732 for (
G4int i = 0; i < limit; ++i)
734 G4int candidate = candidates[i];
739 localPoint = GetLocalPoint(transform, point);
740 G4VSolid& solid = *fSolids[candidate];
741 if (solid.
Inside(localPoint) == EInside::kInside)
744 if (safetyMin > safety) safetyMin = safety;
747 if (safetyMin == kInfinity) safetyMin = 0;
761 const std::vector<G4VoxelBox>& boxes = fVoxels.
GetBoxes();
765 G4int numNodes = fSolids.size();
766 for (
G4int j = 0; j < numNodes; ++j)
773 for (
auto i = 0; i <= 2; ++i)
776 if ((dxyz[i] = std::abs(point[i] - pos[i]) - hlen[i]) > safetyMin)
780 for (
auto i = 0; i <= 2; ++i)
781 if (dxyz[i] > 0) d2xyz += dxyz[i] * dxyz[i];
786 if (d2xyz >= safetyMin * safetyMin)
792 localPoint = GetLocalPoint(transform, point);
796 if (safety <= 0)
return safety;
798 if (safetyMin > safety) safetyMin = safety;
816 fVoxels.
Voxelize(fSolids, fTransformObjs);
827 const std::vector<G4VoxelBox>& boxes = fVoxels.
GetBoxes();
828 safetyMin = kInfinity;
829 G4int safetyNode = 0;
832 G4int numNodes = fSolids.size();
833 for (
G4int i = 0; i < numNodes; ++i)
836 G4double dxyz0 = std::abs(aPoint.
x() - boxes[i].pos.x()) - boxes[i].hlen.x();
837 if (dxyz0 > safetyMin)
continue;
838 G4double dxyz1 = std::abs(aPoint.
y() - boxes[i].pos.y()) - boxes[i].hlen.y();
839 if (dxyz1 > safetyMin)
continue;
840 G4double dxyz2 = std::abs(aPoint.
z() - boxes[i].pos.z()) - boxes[i].hlen.z();
841 if (dxyz2 > safetyMin)
continue;
843 if (dxyz0 > 0) d2xyz += dxyz0 * dxyz0;
844 if (dxyz1 > 0) d2xyz += dxyz1 * dxyz1;
845 if (dxyz2 > 0) d2xyz += dxyz2 * dxyz2;
846 if (d2xyz >= safetyMin * safetyMin)
continue;
850 localPoint = GetLocalPoint(transform, aPoint);
854 if (safetyMin > safety)
883 min.set(kInfinity,kInfinity,kInfinity);
884 max.set(-kInfinity,-kInfinity,-kInfinity);
888 for (
G4int i = 0 ; i < limit; ++i)
892 G4ThreeVector current = GetGlobalPoint(transformation, vertices[i]);
895 if (current.
x() >
max.x())
max.setX(current.
x());
896 if (current.
x() <
min.x())
min.setX(current.
x());
898 if (current.
y() >
max.y())
max.setY(current.
y());
899 if (current.
y() <
min.y())
min.setY(current.
y());
901 if (current.
z() >
max.z())
max.setZ(current.
z());
902 if (current.
z() <
min.z())
min.setZ(current.
z());
910 G4int oldprc = os.precision(16);
911 os <<
"-----------------------------------------------------------\n"
912 <<
" *** Dump for solid - " <<
GetName() <<
" ***\n"
913 <<
" ===================================================\n"
914 <<
" Solid type: G4MultiUnion\n"
915 <<
" Parameters: \n";
916 G4int numNodes = fSolids.size();
917 for (
G4int i = 0 ; i < numNodes ; ++i)
923 os <<
" Rotation is :" <<
" \n";
927 <<
"-----------------------------------------------------------\n";
928 os.precision(oldprc);
938 G4long size = fSolids.size();
946 point = GetGlobalPoint(transform, point);
948 while (
Inside(point) != EInside::kSurface);
978 processor.push_back (operation, *operand);
981 if (
processor.execute(*top)) {
return top; }
988 if (fpPolyhedron ==
nullptr ||
989 fRebuildPolyhedron ||
996 fRebuildPolyhedron =
false;
#define G4MUTEX_INITIALIZER
CLHEP::Hep3Vector G4ThreeVector
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimits, const G4Transform3D &pTransform3D, G4double &pMin, G4double &pMax) const
G4Polyhedron * GetPolyhedron() const
G4double GetRadialTolerance() const
static G4GeometryTolerance * GetInstance()
const G4Transform3D & GetTransformation(G4int index) const
G4int GetNumberOfSolids() const
G4double DistanceToIn(const G4ThreeVector &aPoint) const
G4double GetSurfaceArea()
G4double DistanceToOutNoVoxels(const G4ThreeVector &aPoint, const G4ThreeVector &aDirection, G4ThreeVector *aNormalVector) const
G4double GetCubicVolume()
EInside InsideNoVoxels(const G4ThreeVector &aPoint) const
G4double DistanceToInNoVoxels(const G4ThreeVector &aPoint, const G4ThreeVector &aDirection) const
EInside Inside(const G4ThreeVector &aPoint) const
G4double DistanceToOut(const G4ThreeVector &aPoint) const
G4Polyhedron * CreatePolyhedron() const
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimit, const G4AffineTransform &pTransform, G4double &pMin, G4double &pMax) const
void BoundingLimits(G4ThreeVector &aMin, G4ThreeVector &aMax) const
G4Polyhedron * GetPolyhedron() const
G4double DistanceToOutVoxels(const G4ThreeVector &aPoint, const G4ThreeVector &aDirection, G4ThreeVector *aNormalVector) const
std::ostream & StreamInfo(std::ostream &os) const
void AddNode(G4VSolid &solid, G4Transform3D &trans)
void DescribeYourselfTo(G4VGraphicsScene &scene) const
void Extent(EAxis aAxis, G4double &aMin, G4double &aMax) const
G4ThreeVector GetPointOnSurface() const
G4VSolid * GetSolid(G4int index) const
G4ThreeVector SurfaceNormal(const G4ThreeVector &aPoint) const
G4MultiUnion & operator=(const G4MultiUnion &rhs)
G4int GetNumberOfRotationStepsAtTimeOfCreation() const
void ResetBitNumber(unsigned int bitnumber)
void SetBitNumber(unsigned int bitnumber, G4bool value=true)
virtual void AddSolid(const G4Box &)=0
G4double EstimateSurfaceArea(G4int nStat, G4double ell) const
virtual std::ostream & StreamInfo(std::ostream &os) const =0
virtual EInside Inside(const G4ThreeVector &p) const =0
void SetName(const G4String &name)
virtual G4double DistanceToOut(const G4ThreeVector &p, const G4ThreeVector &v, const G4bool calcNorm=false, G4bool *validNorm=nullptr, G4ThreeVector *n=nullptr) const =0
virtual G4ThreeVector GetPointOnSurface() const
virtual G4ThreeVector SurfaceNormal(const G4ThreeVector &p) const =0
virtual void BoundingLimits(G4ThreeVector &pMin, G4ThreeVector &pMax) const
G4VSolid & operator=(const G4VSolid &rhs)
virtual G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const =0
G4double DistanceToBoundingBox(const G4ThreeVector &point) const
const std::vector< G4VoxelBox > & GetBoxes() const
void GetVoxel(std::vector< G4int > &curVoxel, const G4ThreeVector &point) const
G4int GetBitsPerSlice() const
G4double DistanceToFirst(const G4ThreeVector &point, const G4ThreeVector &direction) const
G4int GetCandidatesVoxelArray(const G4ThreeVector &point, std::vector< G4int > &list, G4SurfBits *crossed=nullptr) const
G4double DistanceToNext(const G4ThreeVector &point, const G4ThreeVector &direction, std::vector< G4int > &curVoxel) const
void Voxelize(std::vector< G4VSolid * > &solids, std::vector< G4Transform3D > &transforms)
static G4int GetNumberOfRotationSteps()
T max(const T t1, const T t2)
brief Return the largest of the two arguments
T min(const T t1, const T t2)
brief Return the smallest of the two arguments