File indexing completed on 2026-04-10 07:50:35
0001 #pragma once
0002
0003 #include <array>
0004 #include <csignal>
0005
0006 #include "G4VPhysicalVolume.hh"
0007 #include "G4Transform3D.hh"
0008 #include "G4RotationMatrix.hh"
0009 #include "G4BooleanSolid.hh"
0010 #include "G4MultiUnion.hh"
0011
0012 #include <glm/glm.hpp>
0013 #include <glm/gtc/type_ptr.hpp>
0014 #include "glm/gtx/string_cast.hpp"
0015
0016 struct U4Transform
0017 {
0018 static void Read( const glm::tmat4x4<double>& dst, const double* src );
0019 static void ReadWide( const glm::tmat4x4<double>& dst, const float* src );
0020
0021 static void WriteTransform( double* dst, const glm::tmat4x4<double>& src );
0022 static void WriteObjectTransform(double* dst, const G4VPhysicalVolume* const pv) ;
0023 static void WriteFrameTransform( double* dst, const G4VPhysicalVolume* const pv) ;
0024
0025 static void GetObjectTransform(glm::tmat4x4<double>& tr, const G4VPhysicalVolume* const pv) ;
0026 static void GetFrameTransform( glm::tmat4x4<double>& tr, const G4VPhysicalVolume* const pv) ;
0027 static void GetDispTransform( glm::tmat4x4<double>& tr, const G4DisplacedSolid* disp );
0028 static void GetMultiUnionItemTransform( glm::tmat4x4<double>& tr, const G4MultiUnion* const muni, unsigned item );
0029
0030 static void GetScaleTransform( glm::tmat4x4<double>& tr, double sx, double sy, double sz );
0031
0032 template<typename T>
0033 static void Convert(glm::tmat4x4<T>& dst, const std::array<T,16>& src );
0034
0035 template<typename T>
0036 static void Convert_RotateThenTranslate(glm::tmat4x4<T>& dst, const G4Transform3D& src );
0037
0038 template<typename T>
0039 static void Convert_RotateThenTranslate(glm::tmat4x4<T>& d, const G4RotationMatrix& rot, const G4ThreeVector& tla, bool f );
0040
0041 template<typename T>
0042 static void Convert_TranslateThenRotate(glm::tmat4x4<T>& dst, const G4Transform3D& src );
0043
0044 template<typename T>
0045 static unsigned Check(const std::array<T,16>& a);
0046 };
0047
0048
0049
0050 inline void U4Transform::WriteTransform( double* dst, const glm::tmat4x4<double>& src )
0051 {
0052 memcpy( dst, glm::value_ptr(src), sizeof(double)*16 );
0053 }
0054 inline void U4Transform::WriteObjectTransform(double* dst, const G4VPhysicalVolume* const pv)
0055 {
0056 glm::tmat4x4<double> tr(1.);
0057 GetObjectTransform(tr, pv );
0058 WriteTransform(dst, tr );
0059 }
0060 inline void U4Transform::WriteFrameTransform(double* dst, const G4VPhysicalVolume* const pv)
0061 {
0062 glm::tmat4x4<double> tr(1.);
0063 GetFrameTransform(tr, pv );
0064 WriteTransform(dst, tr );
0065 }
0066 inline void U4Transform::GetObjectTransform(glm::tmat4x4<double>& tr, const G4VPhysicalVolume* const pv)
0067 {
0068
0069 G4RotationMatrix rot = pv->GetObjectRotationValue() ;
0070 G4ThreeVector tla = pv->GetObjectTranslation() ;
0071 G4Transform3D tra(rot,tla);
0072 Convert_RotateThenTranslate(tr, tra);
0073 }
0074 inline void U4Transform::GetFrameTransform(glm::tmat4x4<double>& tr, const G4VPhysicalVolume* const pv)
0075 {
0076 const G4RotationMatrix* rotp = pv->GetFrameRotation() ;
0077 G4ThreeVector tla = pv->GetFrameTranslation() ;
0078 G4Transform3D tra(rotp ? *rotp : G4RotationMatrix(),tla);
0079 Convert_TranslateThenRotate(tr, tra );
0080 }
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106 inline void U4Transform::GetDispTransform(glm::tmat4x4<double>& tr, const G4DisplacedSolid* disp )
0107 {
0108 assert(disp) ;
0109 G4RotationMatrix rot = disp->GetFrameRotation();
0110 G4ThreeVector tla = disp->GetObjectTranslation();
0111
0112
0113
0114
0115 Convert_RotateThenTranslate(tr, rot, tla, true );
0116 }
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131 inline void U4Transform::GetMultiUnionItemTransform( glm::tmat4x4<double>& xf, const G4MultiUnion* const muni, unsigned item )
0132 {
0133 [[maybe_unused]] unsigned num_item = muni->GetNumberOfSolids() ;
0134 assert( item < num_item );
0135 const G4Transform3D& tr = muni->GetTransformation(item) ;
0136
0137 Convert_RotateThenTranslate(xf, tr );
0138 }
0139
0140
0141
0142 inline void U4Transform::GetScaleTransform( glm::tmat4x4<double>& tr, double sx, double sy, double sz )
0143 {
0144 glm::tvec3<double> sc(sx, sy, sz);
0145 tr = glm::scale(glm::tmat4x4<double>(1.), sc) ;
0146 }
0147
0148
0149
0150
0151
0152 template<typename T>
0153 inline void U4Transform::Convert(glm::tmat4x4<T>& d, const std::array<T,16>& s )
0154 {
0155 unsigned n = Check(s);
0156 bool n_expect = n == 0 ;
0157 assert( n_expect );
0158 if(!n_expect) std::raise(SIGINT);
0159
0160 memcpy( glm::value_ptr(d), s.data(), sizeof(T)*16 );
0161 }
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175
0176
0177
0178 template<typename T>
0179 inline void U4Transform::Convert_RotateThenTranslate(glm::tmat4x4<T>& d, const G4Transform3D& s )
0180 {
0181 T zero(0.);
0182 T one(1.);
0183
0184 std::array<T, 16> a = {{
0185 s.xx(), s.yx(), s.zx(), zero ,
0186 s.xy(), s.yy(), s.zy(), zero ,
0187 s.xz(), s.yz(), s.zz(), zero ,
0188 s.dx(), s.dy(), s.dz(), one }} ;
0189 Convert(d, a);
0190 }
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206 template<typename T>
0207 inline void U4Transform::Convert_RotateThenTranslate(glm::tmat4x4<T>& d, const G4RotationMatrix& r, const G4ThreeVector& t, bool f )
0208 {
0209 T zero(0.);
0210 T one(1.);
0211
0212 if( f == false )
0213 {
0214 std::array<T, 16> a = {{
0215 r.xx(), r.yx(), r.zx(), zero ,
0216 r.xy(), r.yy(), r.zy(), zero ,
0217 r.xz(), r.yz(), r.zz(), zero ,
0218 t.x(), t.y(), t.z(), one }} ;
0219
0220 Convert(d, a);
0221 }
0222 else
0223 {
0224 std::array<T, 16> a = {{
0225 r.xx(), r.xy(), r.xz(), zero ,
0226 r.yx(), r.yy(), r.yz(), zero ,
0227 r.zx(), r.zy(), r.zz(), zero ,
0228 t.x(), t.y(), t.z(), one }} ;
0229
0230 Convert(d, a);
0231 }
0232
0233 }
0234
0235
0236
0237
0238
0239
0240
0241
0242
0243
0244
0245
0246
0247
0248
0249
0250
0251
0252
0253
0254 template<typename T>
0255 inline void U4Transform::Convert_TranslateThenRotate(glm::tmat4x4<T>& d, const G4Transform3D& s )
0256 {
0257 T rxx = s.xx() ;
0258 T rxy = s.xy() ;
0259 T rxz = s.xz() ;
0260
0261 T ryx = s.yx() ;
0262 T ryy = s.yy() ;
0263 T ryz = s.yz() ;
0264
0265 T rzx = s.zx() ;
0266 T rzy = s.zy() ;
0267 T rzz = s.zz() ;
0268
0269 T tx = s.dx() ;
0270 T ty = s.dy() ;
0271 T tz = s.dz() ;
0272
0273 T RTx = rxx*tx + rxy*ty + rxz*tz ;
0274 T RTy = ryx*tx + ryy*ty + ryz*tz ;
0275 T RTz = rzx*tx + rzy*ty + rzz*tz ;
0276
0277 T zero(0.);
0278 T one(1.);
0279 std::array<T, 16> a = {{
0280 rxx , ryx , rzx , zero ,
0281 rxy , ryy , rzy , zero ,
0282 rxz , ryz , rzz , zero ,
0283 RTx , RTy , RTz , one }} ;
0284
0285 unsigned n = Check(a);
0286 bool n_expect = n == 0 ;
0287 assert( n_expect );
0288 if(!n_expect) std::raise(SIGINT);
0289 memcpy( glm::value_ptr(d), a.data(), sizeof(T)*16 );
0290 }
0291
0292
0293
0294
0295
0296
0297 template<typename T>
0298 inline unsigned U4Transform::Check(const std::array<T,16>& a)
0299 {
0300 unsigned num_nan(0);
0301 unsigned num_inf(0);
0302 for(unsigned i=0 ; i < 16 ; i++) if(std::isnan(a[i])) num_nan++ ;
0303 for(unsigned i=0 ; i < 16 ; i++) if(std::isinf(a[i])) num_inf++ ;
0304 return num_nan + num_inf ;
0305 }
0306