62 fTransformObjs.clear();
73 fSolids.push_back(&solid);
74 fTransformObjs.push_back(trans);
80 fSolids.push_back(solid);
81 fTransformObjs.push_back(trans);
93 :
G4VSolid(rhs), fCubicVolume(rhs.fCubicVolume),
94 fSurfaceArea(rhs.fSurfaceArea),
95 kRadTolerance(rhs.kRadTolerance), fAccurate(rhs.fAccurate)
127 if (fCubicVolume == 0.0)
143 std::size_t numNodes = fSolids.size();
144 for (std::size_t i = 0 ; i < numNodes ; ++i)
149 localPoint = GetLocalPoint(transform, aPoint);
150 localDirection = GetLocalVector(transform, direction);
153 if (minDistance > distance) minDistance = distance;
161 std::vector<G4int>& candidates,
164 std::size_t candidatesCount = candidates.size();
168 for (std::size_t i = 0 ; i < candidatesCount; ++i)
170 G4int candidate = candidates[i];
171 G4VSolid& solid = *fSolids[candidate];
174 localPoint = GetLocalPoint(transform, aPoint);
175 localDirection = GetLocalVector(transform, direction);
177 if (minDistance > distance) minDistance = distance;
179 if (minDistance == 0)
break;
200 G4double shift = fVoxels.DistanceToFirst(aPoint, direction);
201 if (shift == kInfinity)
return shift;
204 if (shift != 0.0) currentPoint += direction * shift;
206 G4SurfBits exclusion(fVoxels.GetBitsPerSlice());
207 std::vector<G4int> candidates, curVoxel(3);
208 fVoxels.GetVoxel(curVoxel, currentPoint);
213 if (fVoxels.GetCandidatesVoxelArray(curVoxel, candidates, &exclusion) != 0)
215 G4double distance = DistanceToInCandidates(aPoint, direction,
216 candidates, exclusion);
217 if (minDistance > distance) minDistance = distance;
218 if (distance < shift)
break;
221 shift = fVoxels.DistanceToNext(aPoint, direction, curVoxel);
223 while (minDistance > shift);
243 G4int ignoredSolid = -1;
247 auto numNodes = (
G4int)fSolids.size();
248 for (
auto i = 0; i < numNodes; ++i)
250 if (i != ignoredSolid)
254 localPoint = GetLocalPoint(transform, currentPoint);
255 localDirection = GetLocalVector(transform, direction);
260 false,
nullptr, aNormal);
261 if (distance < kInfinity)
263 if (resultDistToOut == kInfinity) resultDistToOut = 0;
266 currentPoint = GetGlobalPoint(transform, localPoint
267 + distance*localDirection);
268 resultDistToOut += distance;
276 return resultDistToOut;
309 std::vector<G4int> candidates;
311 std::size_t numNodes = 2*fSolids.size();
314 if (fVoxels.GetCandidatesVoxelArray(aPoint, candidates) != 0)
319 G4SurfBits exclusion(fVoxels.GetBitsPerSlice());
328 G4int maxCandidate = 0;
331 std::size_t limit = candidates.size();
332 for (std::size_t i = 0 ; i < limit ; ++i)
334 G4int candidate = candidates[i];
338 G4VSolid& solid = *fSolids[candidate];
343 localPoint = GetLocalPoint(transform, currentPoint);
354 localDirection = GetLocalVector(transform, direction);
358 false,
nullptr, &localNormal);
359 if (maxDistance < shift)
362 maxCandidate = candidate;
363 maxNormal = localNormal;
370 const G4Transform3D& transform = fTransformObjs[maxCandidate];
373 if (aNormal !=
nullptr) *aNormal = GetGlobalVector(transform, maxNormal);
375 distance += maxDistance;
376 currentPoint += maxDistance * direction;
377 if(maxDistance == 0.) ++count;
381 EInside location = InsideWithExclusion(currentPoint, &exclusion);
401 fVoxels.GetCandidatesVoxelArray(currentPoint, candidates, &exclusion);
405 while ((notOutside) && (count < numNodes));
429 std::vector<G4int> candidates;
430 std::vector<G4MultiUnionSurface> surfaces;
440 for (
G4int i = 0 ; i < limit ; ++i)
442 G4int candidate = candidates[i];
443 G4VSolid& solid = *fSolids[candidate];
448 localPoint = GetLocalPoint(transform, aPoint);
449 location = solid.
Inside(localPoint);
453 G4MultiUnionSurface surface;
454 surface.point = localPoint;
455 surface.solid = &solid;
456 surfaces.push_back(surface);
465 std::size_t size = surfaces.size();
472 for (std::size_t i = 0; i < size - 1; ++i)
474 G4MultiUnionSurface& left = surfaces[i];
475 for (std::size_t j = i + 1; j < size; ++j)
477 G4MultiUnionSurface& right = surfaces[j];
479 n = left.solid->SurfaceNormal(left.point);
480 n2 = right.solid->SurfaceNormal(right.point);
481 if ((n + n2).mag2() < 1000 * kRadTolerance)
505 EInside location = InsideWithExclusion(aPoint);
514 G4int countSurface = 0;
516 auto numNodes = (
G4int)fSolids.size();
517 for (
auto i = 0 ; i < numNodes ; ++i)
524 localPoint = GetLocalPoint(transform, aPoint);
526 location = solid.
Inside(localPoint);
543 auto numNodes = (
G4int)fSolids.size();
544 for (
auto i = 0 ; i < numNodes ; ++i)
550 TransformLimits(min, max, transform);
639 std::vector<G4int> candidates;
649 if (fVoxels.GetCandidatesVoxelArray(aPoint, candidates) != 0)
651 std::size_t limit = candidates.size();
652 for (std::size_t i = 0 ; i < limit ; ++i)
654 G4int candidate = candidates[i];
659 localPoint = GetLocalPoint(transform, aPoint);
660 G4VSolid& solid = *fSolids[candidate];
666 normal = GetGlobalVector(transform, solid.
SurfaceNormal(localPoint));
667 return normal.
unit();
685 localPoint = GetLocalPoint(transform, aPoint);
687 normal = GetGlobalVector(transform, solid.
SurfaceNormal(localPoint));
688 return normal.
unit();
695 node = SafetyFromOutsideNumberNode(aPoint, safety);
699 localPoint = GetLocalPoint(transform, aPoint);
703 normal = GetGlobalVector(transform, solid.
SurfaceNormal(localPoint));
705 return normal.
unit();
717 std::vector<G4int> candidates;
723 fVoxels.GetCandidatesVoxelArray(point, candidates);
725 std::size_t limit = candidates.size();
726 for (std::size_t i = 0; i < limit; ++i)
728 G4int candidate = candidates[i];
733 localPoint = GetLocalPoint(transform, point);
734 G4VSolid& solid = *fSolids[candidate];
738 if (safetyMin > safety) safetyMin = safety;
741 if (safetyMin == kInfinity) safetyMin = 0;
753 if (!fAccurate) {
return fVoxels.DistanceToBoundingBox(point); }
755 const std::vector<G4VoxelBox>& boxes = fVoxels.GetBoxes();
759 std::size_t numNodes = fSolids.size();
760 for (std::size_t j = 0; j < numNodes; ++j)
767 for (
auto i = 0; i <= 2; ++i)
770 if ((dxyz[i] = std::abs(point[i] - pos[i]) - hlen[i]) > safetyMin)
774 for (
auto i = 0; i <= 2; ++i)
775 if (dxyz[i] > 0) d2xyz += dxyz[i] * dxyz[i];
780 if (d2xyz >= safetyMin * safetyMin)
786 localPoint = GetLocalPoint(transform, point);
790 if (safety <= 0)
return safety;
792 if (safetyMin > safety) safetyMin = safety;
800 if (fSurfaceArea == 0.0)
818 for (
const auto solid : fSolids) {
if (!solid->
IsFaceted())
return false; }
825 fVoxels.Voxelize(fSolids, fTransformObjs);
836 const std::vector<G4VoxelBox>& boxes = fVoxels.
GetBoxes();
837 safetyMin = kInfinity;
838 std::size_t safetyNode = 0;
841 std::size_t numNodes = fSolids.size();
842 for (std::size_t i = 0; i < numNodes; ++i)
845 G4double dxyz0 = std::abs(aPoint.
x() - boxes[i].pos.x()) - boxes[i].hlen.x();
846 if (dxyz0 > safetyMin)
continue;
847 G4double dxyz1 = std::abs(aPoint.
y() - boxes[i].pos.y()) - boxes[i].hlen.y();
848 if (dxyz1 > safetyMin)
continue;
849 G4double dxyz2 = std::abs(aPoint.
z() - boxes[i].pos.z()) - boxes[i].hlen.z();
850 if (dxyz2 > safetyMin)
continue;
852 if (dxyz0 > 0) d2xyz += dxyz0 * dxyz0;
853 if (dxyz1 > 0) d2xyz += dxyz1 * dxyz1;
854 if (dxyz2 > 0) d2xyz += dxyz2 * dxyz2;
855 if (d2xyz >= safetyMin * safetyMin)
continue;
859 localPoint = GetLocalPoint(transform, aPoint);
863 if (safetyMin > safety)
869 return (
G4int)safetyNode;
892 min.set(kInfinity,kInfinity,kInfinity);
893 max.set(-kInfinity,-kInfinity,-kInfinity);
897 for (
G4int i = 0 ; i < limit; ++i)
901 G4ThreeVector current = GetGlobalPoint(transformation, vertices[i]);
904 if (current.
x() >
max.x())
max.setX(current.
x());
905 if (current.
x() <
min.x())
min.setX(current.
x());
907 if (current.
y() >
max.y())
max.setY(current.
y());
908 if (current.
y() <
min.y())
min.setY(current.
y());
910 if (current.
z() >
max.z())
max.setZ(current.
z());
911 if (current.
z() <
min.z())
min.setZ(current.
z());
919 G4long oldprc = os.precision(16);
920 os <<
"-----------------------------------------------------------\n"
921 <<
" *** Dump for solid - " <<
GetName() <<
" ***\n"
922 <<
" ===================================================\n"
923 <<
" Solid type: G4MultiUnion\n"
924 <<
" Parameters: \n";
925 std::size_t numNodes = fSolids.size();
926 for (std::size_t i = 0 ; i < numNodes ; ++i)
932 os <<
" Rotation is :" <<
" \n";
936 <<
"-----------------------------------------------------------\n";
937 os.precision(oldprc);
947 G4long size = fSolids.size();
955 point = GetGlobalPoint(transform, point);
989 processor.
push_back(operation, *operand);
1010 if (fpPolyhedron ==
nullptr ||
1011 fRebuildPolyhedron ||
1012 fpPolyhedron->GetNumberOfRotationStepsAtTimeOfCreation() !=
1013 fpPolyhedron->GetNumberOfRotationSteps())
1016 delete fpPolyhedron;
1018 fRebuildPolyhedron =
false;
1021 return fpPolyhedron;
G4TemplateAutoLock< G4Mutex > G4AutoLock
#define G4MUTEX_INITIALIZER
CLHEP::Hep3Vector G4ThreeVector
static G4VBooleanProcessor * GetExternalBooleanProcessor()
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimits, const G4Transform3D &pTransform3D, G4double &pMin, G4double &pMax) const
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
EInside InsideNoVoxels(const G4ThreeVector &aPoint) 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)
void ResetBitNumber(unsigned int bitnumber)
void SetBitNumber(unsigned int bitnumber, G4bool value=true)
virtual G4PolyhedronArbitrary * Process(const G4VSolid *)
virtual void AddSolid(const G4Box &)=0
G4double EstimateSurfaceArea(G4int nStat, G4double ell) const
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
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