745{
746 G4double motherMinExtent= kInfinity, motherMaxExtent= -kInfinity,
747 targetMinExtent= kInfinity, targetMaxExtent= -kInfinity;
753 std::size_t nCandidates = pCandidates->size();
754 std::size_t nVol, nNode, targetVolNo;
756
757#ifdef G4GEOMETRY_VOXELDEBUG
758 G4cout <<
"**** G4SmartVoxelHeader::BuildNodes" <<
G4endl
759 <<
" Limits = " << pLimits <<
G4endl
760 <<
" Axis = " << pAxis <<
G4endl
761 <<
" Candidates = " << nCandidates <<
G4endl;
762#endif
763
764
765
766
770 motherMinExtent, motherMaxExtent) )
771 {
773 motherMinExtent, motherMaxExtent);
774 }
777
780 {
781
782
783
786 if (pParam == nullptr)
787 {
788 std::ostringstream message;
789 message <<
"PANIC! - Missing parameterisation." <<
G4endl
790 << " Replicated volume with no parameterisation object !";
791 G4Exception(
"G4SmartVoxelHeader::BuildNodes()",
"GeomMgt0003",
793 return nullptr;
794 }
795
796
797
800 replicated = true;
801 }
802 else
803 {
804 replicated = false;
805 }
806
807
808
809 for (nVol=0; nVol<nCandidates; ++nVol)
810 {
811 targetVolNo = (*pCandidates)[nVol];
812 if (!replicated)
813 {
815
816
817
820
821
823 }
824 else
825 {
826
827
829
830
831
833
834
835
839 }
840
841
843 targetMinExtent, targetMaxExtent))
844 {
846 targetMinExtent,targetMaxExtent);
847 }
848 minExtents[nVol] = targetMinExtent;
849 maxExtents[nVol] = targetMaxExtent;
850
851#ifdef G4GEOMETRY_VOXELDEBUG
852 G4cout <<
"---------------------------------------------------" <<
G4endl
854 <<
" Min Extent = " << targetMinExtent <<
G4endl
855 <<
" Max Extent = " << targetMaxExtent <<
G4endl
856 <<
"---------------------------------------------------" <<
G4endl;
857#endif
858
859
860
861 if ( (!pLimits.
IsLimited()) && ((targetMaxExtent<=motherMinExtent)
862 ||(targetMinExtent>=motherMaxExtent)) )
863 {
864 std::ostringstream message;
865 message <<
"PANIC! - Overlapping daughter with mother volume." <<
G4endl
866 << " Daughter physical volume "
868 << " is entirely outside mother logical volume "
869 << pVolume->
GetName() <<
" !!";
870 G4Exception(
"G4SmartVoxelHeader::BuildNodes()",
"GeomMgt0002",
872 }
873
874#ifdef G4GEOMETRY_VOXELDEBUG
875
876
877
878
880 {
882 G4int kStraddlePercent = 5;
883 width = maxExtents[nVol]-minExtents[nVol];
884 if ( (((motherMinExtent-minExtents[nVol])*100/width) > kStraddlePercent)
885 ||(((maxExtents[nVol]-motherMaxExtent)*100/width) > kStraddlePercent) )
886 {
887 G4cout <<
"**** G4SmartVoxelHeader::BuildNodes" <<
G4endl
888 << " WARNING : Daughter # " << nVol
890 << " Crosses mother boundary of logical volume, name = "
892 << " by more than " << kStraddlePercent
894 }
895 }
896#endif
897 }
898
899
900
901
902
905 for (nVol=0; nVol<nCandidates; ++nVol)
906 {
907
908
909
910
911 currentWidth = std::abs(maxExtents[nVol]-minExtents[nVol]);
912 if ( (currentWidth<minWidth)
915 {
916 minWidth = currentWidth;
917 }
918 }
919
920
921
922
923 G4double noNodesExactD = ((motherMaxExtent-motherMinExtent)*2.0/minWidth)+1.0;
924
925
926
927
928 G4double smartlessComputed = noNodesExactD / nCandidates;
930 G4double smartless = (smartlessComputed <= smartlessUser)
931 ? smartlessComputed : smartlessUser;
932 G4double noNodesSmart = smartless*nCandidates;
933 auto noNodesExactI =
G4int(noNodesSmart);
934 G4long noNodes = ((noNodesSmart-noNodesExactI)>=0.5)
935 ? noNodesExactI+1 : noNodesExactI;
936 if( noNodes == 0 ) { noNodes=1; }
937
938#ifdef G4GEOMETRY_VOXELDEBUG
939 G4cout <<
" Smartless computed = " << smartlessComputed <<
G4endl
940 << " Smartless volume = " << smartlessUser
941 <<
" => # Smartless = " << smartless <<
G4endl;
942 G4cout <<
" Min width = " << minWidth
943 <<
" => # Nodes = " << noNodes <<
G4endl;
944#endif
945
947 {
949#ifdef G4GEOMETRY_VOXELDEBUG
951#endif
952 }
953 G4double nodeWidth = (motherMaxExtent-motherMinExtent)/noNodes;
954
955
956
958 if (nodeList == nullptr)
959 {
960 G4Exception(
"G4SmartVoxelHeader::BuildNodes()",
"GeomMgt0003",
962 return nullptr;
963 }
964 nodeList->reserve(noNodes);
965
966 for (nNode=0;
G4long(nNode)<noNodes; ++nNode)
967 {
970 if (pNode == nullptr)
971 {
972 G4Exception(
"G4SmartVoxelHeader::BuildNodes()",
"GeomMgt0003",
974 return nullptr;
975 }
976 nodeList->push_back(pNode);
977 }
978
979
980
981
982
983 for (nVol=0; nVol<nCandidates; ++nVol)
984 {
985 G4long nodeNo, minContainingNode, maxContainingNode;
986 minContainingNode = (minExtents[nVol]-motherMinExtent)/nodeWidth;
987 maxContainingNode = (maxExtents[nVol]-motherMinExtent)/nodeWidth;
988
989
990
991 if ( (maxContainingNode>=0) && (minContainingNode<noNodes) )
992 {
993
994
995
996 if (maxContainingNode>=noNodes)
997 {
998 maxContainingNode = noNodes-1;
999 }
1000
1001
1002
1003 if (minContainingNode<0)
1004 {
1005 minContainingNode = 0;
1006 }
1007 for (nodeNo=minContainingNode; nodeNo<=maxContainingNode; ++nodeNo)
1008 {
1009 (*nodeList)[nodeNo]->Insert((*pCandidates)[nVol]);
1010 }
1011 }
1012 }
1013
1014
1015
1016
1017
1018
1020 if (proxyList == nullptr)
1021 {
1022 G4Exception(
"G4SmartVoxelHeader::BuildNodes()",
"GeomMgt0003",
1024 return nullptr;
1025 }
1026 proxyList->reserve(noNodes);
1027
1028
1029
1030
1031 for (nNode=0;
G4long(nNode)<noNodes; ++nNode)
1032 {
1033
1034
1035 ((*nodeList)[nNode])->Shrink();
1037 if (pProxyNode == nullptr)
1038 {
1039 G4Exception(
"G4SmartVoxelHeader::BuildNodes()",
"GeomMgt0003",
1041 return nullptr;
1042 }
1043 proxyList->push_back(pProxyNode);
1044 }
1045 delete nodeList;
1046 return proxyList;
1047}
G4VSolid * GetSolid() const
G4double GetSmartless() const
const G4String & GetName() const
virtual G4VSolid * ComputeSolid(const G4int, G4VPhysicalVolume *)
virtual void ComputeTransformation(const G4int, G4VPhysicalVolume *) const =0
const G4RotationMatrix * GetRotation() const
const G4ThreeVector GetTranslation() const
G4LogicalVolume * GetLogicalVolume() const
const G4String & GetName() const
virtual G4VPVParameterisation * GetParameterisation() const =0
virtual G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimit, const G4AffineTransform &pTransform, G4double &pMin, G4double &pMax) const =0
virtual void ComputeDimensions(G4VPVParameterisation *p, const G4int n, const G4VPhysicalVolume *pRep)
G4double GetMinExtent(const EAxis pAxis) const
G4double GetMaxExtent(const EAxis pAxis) const
const G4int kMaxVoxelNodes