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)
130 if (fCubicVolume == 0.0)
133 G4int inside = 0, generated;
135 d = (extentMax - extentMin) / 2.;
136 p = (extentMax + extentMin) / 2.;
139 for (generated = 0; generated < 10000; ++generated)
144 length.
z()*rvec.
z());
147 G4double vbox = (2 * d.
x()) * (2 * d.
y()) * (2 * d.
z());
148 fCubicVolume = inside * vbox / generated;
162 std::size_t numNodes = fSolids.size();
163 for (std::size_t i = 0 ; i < numNodes ; ++i)
168 localPoint = GetLocalPoint(transform, aPoint);
169 localDirection = GetLocalVector(transform, direction);
172 if (minDistance > distance) minDistance = distance;
180 std::vector<G4int>& candidates,
183 std::size_t candidatesCount = candidates.size();
187 for (std::size_t i = 0 ; i < candidatesCount; ++i)
189 G4int candidate = candidates[i];
190 G4VSolid& solid = *fSolids[candidate];
193 localPoint = GetLocalPoint(transform, aPoint);
194 localDirection = GetLocalVector(transform, direction);
196 if (minDistance > distance) minDistance = distance;
198 if (minDistance == 0)
break;
220 if (shift == kInfinity)
return shift;
223 if (shift != 0.0) currentPoint += direction * shift;
226 std::vector<G4int> candidates, curVoxel(3);
227 fVoxels.
GetVoxel(curVoxel, currentPoint);
234 G4double distance = DistanceToInCandidates(aPoint, direction,
235 candidates, exclusion);
236 if (minDistance > distance) minDistance = distance;
237 if (distance < shift)
break;
242 while (minDistance > shift);
262 G4int ignoredSolid = -1;
266 auto numNodes = (
G4int)fSolids.size();
267 for (
auto i = 0; i < numNodes; ++i)
269 if (i != ignoredSolid)
273 localPoint = GetLocalPoint(transform, currentPoint);
274 localDirection = GetLocalVector(transform, direction);
279 false,
nullptr, aNormal);
280 if (distance < kInfinity)
282 if (resultDistToOut == kInfinity) resultDistToOut = 0;
285 currentPoint = GetGlobalPoint(transform, localPoint
286 + distance*localDirection);
287 resultDistToOut += distance;
295 return resultDistToOut;
328 std::vector<G4int> candidates;
330 std::size_t numNodes = 2*fSolids.size();
347 G4int maxCandidate = 0;
350 std::size_t limit = candidates.size();
351 for (std::size_t i = 0 ; i < limit ; ++i)
353 G4int candidate = candidates[i];
357 G4VSolid& solid = *fSolids[candidate];
362 localPoint = GetLocalPoint(transform, currentPoint);
373 localDirection = GetLocalVector(transform, direction);
377 false,
nullptr, &localNormal);
378 if (maxDistance < shift)
381 maxCandidate = candidate;
382 maxNormal = localNormal;
389 const G4Transform3D& transform = fTransformObjs[maxCandidate];
392 if (aNormal !=
nullptr) *aNormal = GetGlobalVector(transform, maxNormal);
394 distance += maxDistance;
395 currentPoint += maxDistance * direction;
396 if(maxDistance == 0.) ++count;
400 EInside location = InsideWithExclusion(currentPoint, &exclusion);
424 while ((notOutside) && (count < numNodes));
448 std::vector<G4int> candidates;
449 std::vector<G4MultiUnionSurface> surfaces;
459 for (
G4int i = 0 ; i < limit ; ++i)
461 G4int candidate = candidates[i];
462 G4VSolid& solid = *fSolids[candidate];
467 localPoint = GetLocalPoint(transform, aPoint);
468 location = solid.
Inside(localPoint);
472 G4MultiUnionSurface surface;
473 surface.point = localPoint;
474 surface.solid = &solid;
475 surfaces.push_back(surface);
484 std::size_t size = surfaces.size();
491 for (std::size_t i = 0; i < size - 1; ++i)
493 G4MultiUnionSurface& left = surfaces[i];
494 for (std::size_t j = i + 1; j < size; ++j)
496 G4MultiUnionSurface& right = surfaces[j];
498 n = left.solid->SurfaceNormal(left.point);
499 n2 = right.solid->SurfaceNormal(right.point);
500 if ((n + n2).mag2() < 1000 * kRadTolerance)
524 EInside location = InsideWithExclusion(aPoint);
533 G4int countSurface = 0;
535 auto numNodes = (
G4int)fSolids.size();
536 for (
auto i = 0 ; i < numNodes ; ++i)
543 localPoint = GetLocalPoint(transform, aPoint);
545 location = solid.
Inside(localPoint);
562 auto numNodes = (
G4int)fSolids.size();
563 for (
auto i = 0 ; i < numNodes ; ++i)
569 TransformLimits(min, max, transform);
658 std::vector<G4int> candidates;
670 std::size_t limit = candidates.size();
671 for (std::size_t i = 0 ; i < limit ; ++i)
673 G4int candidate = candidates[i];
678 localPoint = GetLocalPoint(transform, aPoint);
679 G4VSolid& solid = *fSolids[candidate];
685 normal = GetGlobalVector(transform, solid.
SurfaceNormal(localPoint));
686 return normal.
unit();
704 localPoint = GetLocalPoint(transform, aPoint);
706 normal = GetGlobalVector(transform, solid.
SurfaceNormal(localPoint));
707 return normal.
unit();
714 node = SafetyFromOutsideNumberNode(aPoint, safety);
718 localPoint = GetLocalPoint(transform, aPoint);
722 normal = GetGlobalVector(transform, solid.
SurfaceNormal(localPoint));
724 return normal.
unit();
736 std::vector<G4int> candidates;
744 std::size_t limit = candidates.size();
745 for (std::size_t i = 0; i < limit; ++i)
747 G4int candidate = candidates[i];
752 localPoint = GetLocalPoint(transform, point);
753 G4VSolid& solid = *fSolids[candidate];
757 if (safetyMin > safety) safetyMin = safety;
760 if (safetyMin == kInfinity) safetyMin = 0;
774 const std::vector<G4VoxelBox>& boxes = fVoxels.
GetBoxes();
778 std::size_t numNodes = fSolids.size();
779 for (std::size_t j = 0; j < numNodes; ++j)
786 for (
auto i = 0; i <= 2; ++i)
789 if ((dxyz[i] = std::abs(point[i] - pos[i]) - hlen[i]) > safetyMin)
793 for (
auto i = 0; i <= 2; ++i)
794 if (dxyz[i] > 0) d2xyz += dxyz[i] * dxyz[i];
799 if (d2xyz >= safetyMin * safetyMin)
805 localPoint = GetLocalPoint(transform, point);
809 if (safety <= 0)
return safety;
811 if (safetyMin > safety) safetyMin = safety;
819 if (fSurfaceArea == 0.0)
829 fVoxels.
Voxelize(fSolids, fTransformObjs);
840 const std::vector<G4VoxelBox>& boxes = fVoxels.
GetBoxes();
841 safetyMin = kInfinity;
842 std::size_t safetyNode = 0;
845 std::size_t numNodes = fSolids.size();
846 for (std::size_t i = 0; i < numNodes; ++i)
849 G4double dxyz0 = std::abs(aPoint.
x() - boxes[i].pos.x()) - boxes[i].hlen.x();
850 if (dxyz0 > safetyMin)
continue;
851 G4double dxyz1 = std::abs(aPoint.
y() - boxes[i].pos.y()) - boxes[i].hlen.y();
852 if (dxyz1 > safetyMin)
continue;
853 G4double dxyz2 = std::abs(aPoint.
z() - boxes[i].pos.z()) - boxes[i].hlen.z();
854 if (dxyz2 > safetyMin)
continue;
856 if (dxyz0 > 0) d2xyz += dxyz0 * dxyz0;
857 if (dxyz1 > 0) d2xyz += dxyz1 * dxyz1;
858 if (dxyz2 > 0) d2xyz += dxyz2 * dxyz2;
859 if (d2xyz >= safetyMin * safetyMin)
continue;
863 localPoint = GetLocalPoint(transform, aPoint);
867 if (safetyMin > safety)
873 return (
G4int)safetyNode;
896 min.set(kInfinity,kInfinity,kInfinity);
897 max.set(-kInfinity,-kInfinity,-kInfinity);
901 for (
G4int i = 0 ; i < limit; ++i)
905 G4ThreeVector current = GetGlobalPoint(transformation, vertices[i]);
908 if (current.
x() >
max.x())
max.setX(current.
x());
909 if (current.
x() <
min.x())
min.setX(current.
x());
911 if (current.
y() >
max.y())
max.setY(current.
y());
912 if (current.
y() <
min.y())
min.setY(current.
y());
914 if (current.
z() >
max.z())
max.setZ(current.
z());
915 if (current.
z() <
min.z())
min.setZ(current.
z());
923 G4long oldprc = os.precision(16);
924 os <<
"-----------------------------------------------------------\n"
925 <<
" *** Dump for solid - " <<
GetName() <<
" ***\n"
926 <<
" ===================================================\n"
927 <<
" Solid type: G4MultiUnion\n"
928 <<
" Parameters: \n";
929 std::size_t numNodes = fSolids.size();
930 for (std::size_t i = 0 ; i < numNodes ; ++i)
936 os <<
" Rotation is :" <<
" \n";
940 <<
"-----------------------------------------------------------\n";
941 os.precision(oldprc);
951 G4long size = fSolids.size();
959 point = GetGlobalPoint(transform, point);
993 processor.
push_back(operation, *operand);
1023 return solidAPolyhedron;
1030 if (fpPolyhedron ==
nullptr ||
1031 fRebuildPolyhedron ||
1036 delete fpPolyhedron;
1038 fRebuildPolyhedron =
false;
1041 return fpPolyhedron;
#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
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
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)
G4int GetNumberOfRotationStepsAtTimeOfCreation() const
void ResetBitNumber(unsigned int bitnumber)
void SetBitNumber(unsigned int bitnumber, G4bool value=true)
virtual G4PolyhedronArbitrary * Union(G4Polyhedron *, G4Polyhedron *)
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 G4Polyhedron * GetPolyhedron() const
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)
bool execute(HepPolyhedron &)
void push_back(Operation, const HepPolyhedron &)
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