59 fTransformObjs.clear();
71 fSolids.push_back(&solid);
72 fTransformObjs.push_back(trans);
78 fSolids.push_back(solid);
79 fTransformObjs.push_back(trans);
91 :
G4VSolid(rhs), fCubicVolume(rhs.fCubicVolume),
92 fSurfaceArea(rhs.fSurfaceArea),
93 kRadTolerance(rhs.kRadTolerance), fAccurate(rhs.fAccurate)
131 G4int inside = 0, generated;
133 d = (extentMax - extentMin) / 2.;
134 p = (extentMax + extentMin) / 2.;
137 for (generated = 0; generated < 10000; ++generated)
142 length.
z()*rvec.
z());
143 if (
Inside(point) != EInside::kOutside) ++inside;
145 G4double vbox = (2 * d.
x()) * (2 * d.
y()) * (2 * d.
z());
146 fCubicVolume = inside * vbox / generated;
160 std::size_t numNodes = fSolids.size();
161 for (std::size_t i = 0 ; i < numNodes ; ++i)
166 localPoint = GetLocalPoint(transform, aPoint);
167 localDirection = GetLocalVector(transform, direction);
170 if (minDistance > distance) minDistance = distance;
178 std::vector<G4int>& candidates,
181 std::size_t candidatesCount = candidates.size();
185 for (std::size_t i = 0 ; i < candidatesCount; ++i)
187 G4int candidate = candidates[i];
188 G4VSolid& solid = *fSolids[candidate];
191 localPoint = GetLocalPoint(transform, aPoint);
192 localDirection = GetLocalVector(transform, direction);
194 if (minDistance > distance) minDistance = distance;
196 if (minDistance == 0)
break;
218 if (shift == kInfinity)
return shift;
221 if (shift) currentPoint += direction * shift;
224 std::vector<G4int> candidates, curVoxel(3);
225 fVoxels.
GetVoxel(curVoxel, currentPoint);
232 G4double distance = DistanceToInCandidates(aPoint, direction,
233 candidates, exclusion);
234 if (minDistance > distance) minDistance = distance;
235 if (distance < shift)
break;
240 while (minDistance > shift);
260 G4int ignoredSolid = -1;
265 for (
auto i = 0; i < numNodes; ++i)
267 if (i != ignoredSolid)
271 localPoint = GetLocalPoint(transform, currentPoint);
272 localDirection = GetLocalVector(transform, direction);
274 if (location != EInside::kOutside)
278 if (distance < kInfinity)
280 if (resultDistToOut == kInfinity) resultDistToOut = 0;
283 currentPoint = GetGlobalPoint(transform, localPoint
284 + distance*localDirection);
285 resultDistToOut += distance;
293 return resultDistToOut;
326 std::vector<G4int> candidates;
328 std::size_t numNodes = 2*fSolids.size();
345 G4int maxCandidate = 0;
348 std::size_t limit = candidates.size();
349 for (std::size_t i = 0 ; i < limit ; ++i)
351 G4int candidate = candidates[i];
355 G4VSolid& solid = *fSolids[candidate];
360 localPoint = GetLocalPoint(transform, currentPoint);
367 if (solid.
Inside(localPoint) != EInside::kOutside)
371 localDirection = GetLocalVector(transform, direction);
375 false, 0, &localNormal);
376 if (maxDistance < shift)
379 maxCandidate = candidate;
380 maxNormal = localNormal;
387 const G4Transform3D& transform = fTransformObjs[maxCandidate];
390 if (aNormal) *aNormal = GetGlobalVector(transform, maxNormal);
392 distance += maxDistance;
393 currentPoint += maxDistance * direction;
394 if(maxDistance == 0.) ++count;
398 EInside location = InsideWithExclusion(currentPoint, &exclusion);
405 if (location == EInside::kOutside)
422 while ((notOutside) && (count < numNodes));
444 EInside location = EInside::kOutside;
446 std::vector<G4int> candidates;
447 std::vector<G4MultiUnionSurface> surfaces;
457 for (
G4int i = 0 ; i < limit ; ++i)
459 G4int candidate = candidates[i];
460 G4VSolid& solid = *fSolids[candidate];
465 localPoint = GetLocalPoint(transform, aPoint);
466 location = solid.
Inside(localPoint);
467 if (location == EInside::kInside)
return EInside::kInside;
468 else if (location == EInside::kSurface)
470 G4MultiUnionSurface surface;
471 surface.point = localPoint;
472 surface.solid = &solid;
473 surfaces.push_back(surface);
482 std::size_t size = surfaces.size();
486 return EInside::kOutside;
489 for (std::size_t i = 0; i < size - 1; ++i)
491 G4MultiUnionSurface& left = surfaces[i];
492 for (std::size_t j = i + 1; j < size; ++j)
494 G4MultiUnionSurface& right = surfaces[j];
496 n = left.solid->SurfaceNormal(left.point);
497 n2 = right.solid->SurfaceNormal(right.point);
498 if ((n + n2).mag2() < 1000 * kRadTolerance)
499 return EInside::kInside;
503 return EInside::kSurface;
522 EInside location = InsideWithExclusion(aPoint);
530 EInside location = EInside::kOutside;
531 G4int countSurface = 0;
534 for (
auto i = 0 ; i < numNodes ; ++i)
541 localPoint = GetLocalPoint(transform, aPoint);
543 location = solid.
Inside(localPoint);
545 if (location == EInside::kSurface)
548 if (location == EInside::kInside)
return EInside::kInside;
550 if (countSurface != 0)
return EInside::kSurface;
551 return EInside::kOutside;
561 for (
auto i = 0 ; i < numNodes ; ++i)
567 TransformLimits(min, max, transform);
656 std::vector<G4int> candidates;
668 std::size_t limit = candidates.size();
669 for (std::size_t i = 0 ; i < limit ; ++i)
671 G4int candidate = candidates[i];
676 localPoint = GetLocalPoint(transform, aPoint);
677 G4VSolid& solid = *fSolids[candidate];
680 if (location == EInside::kSurface)
683 normal = GetGlobalVector(transform, solid.
SurfaceNormal(localPoint));
684 return normal.
unit();
689 G4double s = (location == EInside::kInside)
702 localPoint = GetLocalPoint(transform, aPoint);
704 normal = GetGlobalVector(transform, solid.
SurfaceNormal(localPoint));
705 return normal.
unit();
712 node = SafetyFromOutsideNumberNode(aPoint, safety);
716 localPoint = GetLocalPoint(transform, aPoint);
720 normal = GetGlobalVector(transform, solid.
SurfaceNormal(localPoint));
722 return normal.
unit();
734 std::vector<G4int> candidates;
742 std::size_t limit = candidates.size();
743 for (std::size_t i = 0; i < limit; ++i)
745 G4int candidate = candidates[i];
750 localPoint = GetLocalPoint(transform, point);
751 G4VSolid& solid = *fSolids[candidate];
752 if (solid.
Inside(localPoint) == EInside::kInside)
755 if (safetyMin > safety) safetyMin = safety;
758 if (safetyMin == kInfinity) safetyMin = 0;
772 const std::vector<G4VoxelBox>& boxes = fVoxels.
GetBoxes();
776 std::size_t numNodes = fSolids.size();
777 for (std::size_t j = 0; j < numNodes; ++j)
784 for (
auto i = 0; i <= 2; ++i)
787 if ((dxyz[i] = std::abs(point[i] - pos[i]) - hlen[i]) > safetyMin)
791 for (
auto i = 0; i <= 2; ++i)
792 if (dxyz[i] > 0) d2xyz += dxyz[i] * dxyz[i];
797 if (d2xyz >= safetyMin * safetyMin)
803 localPoint = GetLocalPoint(transform, point);
807 if (safety <= 0)
return safety;
809 if (safetyMin > safety) safetyMin = safety;
827 fVoxels.
Voxelize(fSolids, fTransformObjs);
838 const std::vector<G4VoxelBox>& boxes = fVoxels.
GetBoxes();
839 safetyMin = kInfinity;
840 std::size_t safetyNode = 0;
843 std::size_t numNodes = fSolids.size();
844 for (std::size_t i = 0; i < numNodes; ++i)
847 G4double dxyz0 = std::abs(aPoint.
x() - boxes[i].pos.x()) - boxes[i].hlen.x();
848 if (dxyz0 > safetyMin)
continue;
849 G4double dxyz1 = std::abs(aPoint.
y() - boxes[i].pos.y()) - boxes[i].hlen.y();
850 if (dxyz1 > safetyMin)
continue;
851 G4double dxyz2 = std::abs(aPoint.
z() - boxes[i].pos.z()) - boxes[i].hlen.z();
852 if (dxyz2 > safetyMin)
continue;
854 if (dxyz0 > 0) d2xyz += dxyz0 * dxyz0;
855 if (dxyz1 > 0) d2xyz += dxyz1 * dxyz1;
856 if (dxyz2 > 0) d2xyz += dxyz2 * dxyz2;
857 if (d2xyz >= safetyMin * safetyMin)
continue;
861 localPoint = GetLocalPoint(transform, aPoint);
865 if (safetyMin > safety)
871 return (
G4int)safetyNode;
894 min.set(kInfinity,kInfinity,kInfinity);
895 max.set(-kInfinity,-kInfinity,-kInfinity);
899 for (
G4int i = 0 ; i < limit; ++i)
903 G4ThreeVector current = GetGlobalPoint(transformation, vertices[i]);
906 if (current.
x() >
max.x())
max.setX(current.
x());
907 if (current.
x() <
min.x())
min.setX(current.
x());
909 if (current.
y() >
max.y())
max.setY(current.
y());
910 if (current.
y() <
min.y())
min.setY(current.
y());
912 if (current.
z() >
max.z())
max.setZ(current.
z());
913 if (current.
z() <
min.z())
min.setZ(current.
z());
921 G4long oldprc = os.precision(16);
922 os <<
"-----------------------------------------------------------\n"
923 <<
" *** Dump for solid - " <<
GetName() <<
" ***\n"
924 <<
" ===================================================\n"
925 <<
" Solid type: G4MultiUnion\n"
926 <<
" Parameters: \n";
927 std::size_t numNodes = fSolids.size();
928 for (std::size_t i = 0 ; i < numNodes ; ++i)
934 os <<
" Rotation is :" <<
" \n";
938 <<
"-----------------------------------------------------------\n";
939 os.precision(oldprc);
949 G4long size = fSolids.size();
957 point = GetGlobalPoint(transform, point);
959 while (
Inside(point) != EInside::kSurface);
989 processor.
push_back (operation, *operand);
992 if (processor.
execute(*top)) {
return top; }
999 if (fpPolyhedron ==
nullptr ||
1000 fRebuildPolyhedron ||
1005 delete fpPolyhedron;
1007 fRebuildPolyhedron =
false;
1010 return fpPolyhedron;
#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 DescribeYourselfTo(G4VGraphicsScene &scene) const
void AddNode(G4VSolid &solid, const G4Transform3D &trans)
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)
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