68 fTransformObjs.clear();
75 fSolids.push_back(&solid);
76 fTransformObjs.push_back(trans);
82 fSolids.push_back(solid);
83 fTransformObjs.push_back(trans);
95 :
G4VSolid(rhs), fCubicVolume(rhs.fCubicVolume),
96 fSurfaceArea(rhs.fSurfaceArea),
97 kRadTolerance(rhs.kRadTolerance), fAccurate(rhs.fAccurate)
135 std::size_t numNodes = fSolids.size();
136 for (std::size_t i = 0 ; i < numNodes ; ++i)
141 localPoint = GetLocalPoint(transform, aPoint);
142 localDirection = GetLocalVector(transform, direction);
145 if (minDistance > distance) { minDistance = distance; }
153 std::vector<G4int>& candidates,
156 std::size_t candidatesCount = candidates.size();
160 for (std::size_t i = 0 ; i < candidatesCount; ++i)
162 G4int candidate = candidates[i];
163 G4VSolid& solid = *fSolids[candidate];
166 localPoint = GetLocalPoint(transform, aPoint);
167 localDirection = GetLocalVector(transform, direction);
169 if (minDistance > distance) { minDistance = distance; }
171 if (minDistance == 0) {
break; }
192 G4double shift = fVoxels.DistanceToFirst(aPoint, direction);
193 if (shift == kInfinity) {
return shift; }
196 if (shift != 0.0) { currentPoint += direction * shift; }
198 G4SurfBits exclusion(fVoxels.GetBitsPerSlice());
199 std::vector<G4int> candidates, curVoxel(3);
200 fVoxels.GetVoxel(curVoxel, currentPoint);
205 if (fVoxels.GetCandidatesVoxelArray(curVoxel, candidates, &exclusion) != 0)
207 G4double distance = DistanceToInCandidates(aPoint, direction,
208 candidates, exclusion);
209 if (minDistance > distance) { minDistance = distance; }
210 if (distance < shift) {
break; }
213 shift = fVoxels.DistanceToNext(aPoint, direction, curVoxel);
215 while (minDistance > shift);
235 G4int ignoredSolid = -1;
239 auto numNodes = (
G4int)fSolids.size();
240 for (
auto i = 0; i < numNodes; ++i)
242 if (i != ignoredSolid)
246 localPoint = GetLocalPoint(transform, currentPoint);
247 localDirection = GetLocalVector(transform, direction);
252 false,
nullptr, aNormal);
253 if (distance < kInfinity)
255 if (resultDistToOut == kInfinity) { resultDistToOut = 0; }
258 currentPoint = GetGlobalPoint(transform, localPoint
259 + distance*localDirection);
260 resultDistToOut += distance;
268 return resultDistToOut;
301 std::vector<G4int> candidates;
303 std::size_t numNodes = 2*fSolids.size();
306 if (fVoxels.GetCandidatesVoxelArray(aPoint, candidates) != 0)
311 G4SurfBits exclusion(fVoxels.GetBitsPerSlice());
320 G4int maxCandidate = 0;
323 std::size_t limit = candidates.size();
324 for (std::size_t i = 0 ; i < limit ; ++i)
326 G4int candidate = candidates[i];
330 G4VSolid& solid = *fSolids[candidate];
335 localPoint = GetLocalPoint(transform, currentPoint);
346 localDirection = GetLocalVector(transform, direction);
350 false,
nullptr, &localNormal);
351 if (maxDistance < shift)
354 maxCandidate = candidate;
355 maxNormal = localNormal;
362 const G4Transform3D& transform = fTransformObjs[maxCandidate];
365 if (aNormal !=
nullptr)
367 *aNormal = GetGlobalVector(transform, maxNormal);
370 distance += maxDistance;
371 currentPoint += maxDistance * direction;
372 if(maxDistance == 0.) { ++count; }
376 EInside location = InsideWithExclusion(currentPoint, &exclusion);
396 fVoxels.GetCandidatesVoxelArray(currentPoint, candidates, &exclusion);
400 while ((notOutside) && (count < numNodes));
424 std::vector<G4int> candidates;
425 std::vector<G4MultiUnionSurface> surfaces;
435 for (
G4int i = 0 ; i < limit ; ++i)
437 G4int candidate = candidates[i];
438 G4VSolid& solid = *fSolids[candidate];
443 localPoint = GetLocalPoint(transform, aPoint);
444 location = solid.
Inside(localPoint);
451 G4MultiUnionSurface surface;
452 surface.point = localPoint;
453 surface.solid = &solid;
454 surfaces.push_back(surface);
463 std::size_t size = surfaces.size();
470 for (std::size_t i = 0; i < size - 1; ++i)
472 G4MultiUnionSurface& left = surfaces[i];
473 for (std::size_t j = i + 1; j < size; ++j)
475 G4MultiUnionSurface& right = surfaces[j];
477 n = left.solid->SurfaceNormal(left.point);
478 n2 = right.solid->SurfaceNormal(right.point);
479 if ((n + n2).mag2() < 1000 * kRadTolerance)
492 return InsideWithExclusion(aPoint);
500 G4int countSurface = 0;
502 auto numNodes = (
G4int)fSolids.size();
503 for (
auto i = 0 ; i < numNodes ; ++i)
510 localPoint = GetLocalPoint(transform, aPoint);
512 location = solid.
Inside(localPoint);
529 auto numNodes = (
G4int)fSolids.size();
530 for (
auto i = 0 ; i < numNodes ; ++i)
536 TransformLimits(min, max, transform);
564 if (min.x() < aMin) { aMin = min.x(); }
565 if (max.x() > aMax) { aMax = max.x(); }
568 if (min.y() < aMin) { aMin = min.y(); }
569 if (max.y() > aMax) { aMax = max.y(); }
572 if (min.z() < aMin) { aMin = min.z(); }
573 if (max.z() > aMax) { aMax = max.z(); }
619 std::vector<G4int> candidates;
629 if (fVoxels.GetCandidatesVoxelArray(aPoint, candidates) != 0)
631 std::size_t limit = candidates.size();
632 for (std::size_t i = 0 ; i < limit ; ++i)
634 G4int candidate = candidates[i];
639 localPoint = GetLocalPoint(transform, aPoint);
640 G4VSolid& solid = *fSolids[candidate];
646 normal = GetGlobalVector(transform, solid.
SurfaceNormal(localPoint));
647 return normal.
unit();
663 localPoint = GetLocalPoint(transform, aPoint);
665 normal = GetGlobalVector(transform, solid.
SurfaceNormal(localPoint));
666 return normal.
unit();
672 node = SafetyFromOutsideNumberNode(aPoint, safety);
676 localPoint = GetLocalPoint(transform, aPoint);
680 normal = GetGlobalVector(transform, solid.
SurfaceNormal(localPoint));
682 return normal.
unit();
693 std::vector<G4int> candidates;
699 fVoxels.GetCandidatesVoxelArray(point, candidates);
701 std::size_t limit = candidates.size();
702 for (std::size_t i = 0; i < limit; ++i)
704 G4int candidate = candidates[i];
709 localPoint = GetLocalPoint(transform, point);
710 G4VSolid& solid = *fSolids[candidate];
714 if (safetyMin > safety) { safetyMin = safety; }
717 if (safetyMin == kInfinity) { safetyMin = 0; }
729 if (!fAccurate) {
return fVoxels.DistanceToBoundingBox(point); }
731 const std::vector<G4VoxelBox>& boxes = fVoxels.GetBoxes();
735 std::size_t numNodes = fSolids.size();
736 for (std::size_t j = 0; j < numNodes; ++j)
743 for (
auto i = 0; i <= 2; ++i)
747 if ((dxyz[i] = std::abs(point[i] - pos[i]) - hlen[i]) > safetyMin)
754 for (
auto i = 0; i <= 2; ++i)
756 if (dxyz[i] > 0) { d2xyz += dxyz[i] * dxyz[i]; }
762 if (d2xyz >= safetyMin * safetyMin)
768 localPoint = GetLocalPoint(transform, point);
772 if (safety <= 0) {
return safety; }
774 if (safetyMin > safety) { safetyMin = safety; }
783 for (
const auto solid : fSolids)
793 for (
const auto solid : fSolids)
795 if (!solid->
IsFaceted()) {
return false; }
803 fVoxels.Voxelize(fSolids, fTransformObjs);
814 const std::vector<G4VoxelBox>& boxes = fVoxels.
GetBoxes();
815 safetyMin = kInfinity;
816 std::size_t safetyNode = 0;
819 std::size_t numNodes = fSolids.size();
820 for (std::size_t i = 0; i < numNodes; ++i)
823 G4double dxyz0 = std::abs(aPoint.
x() - boxes[i].pos.x()) - boxes[i].hlen.x();
824 if (dxyz0 > safetyMin) {
continue; }
825 G4double dxyz1 = std::abs(aPoint.
y() - boxes[i].pos.y()) - boxes[i].hlen.y();
826 if (dxyz1 > safetyMin) {
continue; }
827 G4double dxyz2 = std::abs(aPoint.
z() - boxes[i].pos.z()) - boxes[i].hlen.z();
828 if (dxyz2 > safetyMin) {
continue; }
830 if (dxyz0 > 0) { d2xyz += dxyz0 * dxyz0; }
831 if (dxyz1 > 0) { d2xyz += dxyz1 * dxyz1; }
832 if (dxyz2 > 0) { d2xyz += dxyz2 * dxyz2; }
833 if (d2xyz >= safetyMin * safetyMin) {
continue; }
837 localPoint = GetLocalPoint(transform, aPoint);
841 if (safetyMin > safety)
847 return (
G4int)safetyNode;
870 min.set(kInfinity,kInfinity,kInfinity);
871 max.set(-kInfinity,-kInfinity,-kInfinity);
875 for (
G4int i = 0 ; i < limit; ++i)
879 G4ThreeVector current = GetGlobalPoint(transformation, vertices[i]);
882 if (current.
x() >
max.x()) {
max.setX(current.
x()); }
883 if (current.
x() <
min.x()) {
min.setX(current.
x()); }
885 if (current.
y() >
max.y()) {
max.setY(current.
y()); }
886 if (current.
y() <
min.y()) {
min.setY(current.
y()); }
888 if (current.
z() >
max.z()) {
max.setZ(current.
z()); }
889 if (current.
z() <
min.z()) {
min.setZ(current.
z()); }
897 G4long oldprc = os.precision(16);
898 os <<
"-----------------------------------------------------------\n"
899 <<
" *** Dump for solid - " <<
GetName() <<
" ***\n"
900 <<
" ===================================================\n"
901 <<
" Solid type: G4MultiUnion\n"
902 <<
" Parameters: \n";
903 std::size_t numNodes = fSolids.size();
904 for (std::size_t i = 0 ; i < numNodes ; ++i)
910 os <<
" Rotation is :" <<
" \n";
914 <<
"-----------------------------------------------------------\n";
915 os.precision(oldprc);
924 G4long size = fSolids.size();
931 point = GetGlobalPoint(transform, p);
940 if (fCubicVolume == 0)
952 if (fSurfaceArea == 0)
988 processor.
push_back(operation, *operand);
1006 if (fpPolyhedron ==
nullptr ||
1007 fRebuildPolyhedron ||
1008 fpPolyhedron->GetNumberOfRotationStepsAtTimeOfCreation() !=
1009 fpPolyhedron->GetNumberOfRotationSteps())
1012 delete fpPolyhedron;
1014 fRebuildPolyhedron =
false;
1017 return fpPolyhedron;
G4TemplateAutoLock< G4Mutex > G4AutoLock
G4double G4QuickRand(uint32_t seed=0)
#define G4MUTEX_INITIALIZER
CLHEP::Hep3Vector G4ThreeVector
static G4VBooleanProcessor * GetExternalBooleanProcessor()
G4BoundingEnvelope is a helper class to facilitate calculation of the extent of a solid within the li...
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimits, const G4Transform3D &pTransform3D, G4double &pMin, G4double &pMax) const
G4DisplacedSolid is a solid that has been shifted from its original frame of reference to a new one....
G4Polyhedron * GetPolyhedron() const override
G4double GetRadialTolerance() const
static G4GeometryTolerance * GetInstance()
const G4Transform3D & GetTransformation(G4int index) const
G4int GetNumberOfSolids() const
G4ThreeVector SurfaceNormal(const G4ThreeVector &aPoint) const override
G4ThreeVector GetPointOnSurface() const override
G4double GetCubicVolume() override
void DescribeYourselfTo(G4VGraphicsScene &scene) const override
void BoundingLimits(G4ThreeVector &aMin, G4ThreeVector &aMax) const override
G4double DistanceToOutNoVoxels(const G4ThreeVector &aPoint, const G4ThreeVector &aDirection, G4ThreeVector *aNormalVector) const
G4VSolid * Clone() const override
G4double DistanceToInNoVoxels(const G4ThreeVector &aPoint, const G4ThreeVector &aDirection) const
G4double GetSurfaceArea() override
G4int GetNumOfConstituents() const override
G4Polyhedron * CreatePolyhedron() const override
G4double DistanceToOutVoxels(const G4ThreeVector &aPoint, const G4ThreeVector &aDirection, G4ThreeVector *aNormalVector) const
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimit, const G4AffineTransform &pTransform, G4double &pMin, G4double &pMax) const override
std::ostream & StreamInfo(std::ostream &os) const override
G4double DistanceToIn(const G4ThreeVector &aPoint) const override
void AddNode(G4VSolid &solid, const G4Transform3D &trans)
G4double DistanceToOut(const G4ThreeVector &aPoint) const override
G4bool IsFaceted() const override
void Extent(EAxis aAxis, G4double &aMin, G4double &aMax) const
G4VSolid * GetSolid(G4int index) const
EInside Inside(const G4ThreeVector &aPoint) const override
G4Polyhedron * GetPolyhedron() const override
G4MultiUnion & operator=(const G4MultiUnion &rhs)
G4SurfBits provides a simple container of bits, to be used for optimization of tessellated surfaces....
void ResetBitNumber(unsigned int bitnumber)
void SetBitNumber(unsigned int bitnumber, G4bool value=true)
virtual G4PolyhedronArbitrary * Process(const G4VSolid *)
virtual void AddSolid(const G4Box &)=0
G4VSolid is an abstract base class for solids, physical shapes that can be tracked through....
virtual std::ostream & StreamInfo(std::ostream &os) const =0
G4double EstimateCubicVolume(G4int nStat, G4double epsilon) const
virtual G4bool IsFaceted() const
G4VSolid(const G4String &name)
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 G4int GetNumOfConstituents() const
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 EstimateSurfaceArea(G4int nStat, G4double epsilon) const
G4VoxelLimits represents limitation/restrictions of space, where restrictions are only made perpendic...
const std::vector< G4VoxelBox > & GetBoxes() const
G4int GetCandidatesVoxelArray(const G4ThreeVector &point, std::vector< G4int > &list, G4SurfBits *crossed=nullptr) const
bool execute(HepPolyhedron &)
void push_back(Operation, const HepPolyhedron &)
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