Geant4 Cross Reference |
1 // 1 // 2 // ******************************************* 2 // ******************************************************************** 3 // * License and Disclaimer << 3 // * DISCLAIMER * 4 // * 4 // * * 5 // * The Geant4 software is copyright of th << 5 // * The following disclaimer summarizes all the specific disclaimers * 6 // * the Geant4 Collaboration. It is provided << 6 // * of contributors to this software. The specific disclaimers,which * 7 // * conditions of the Geant4 Software License << 7 // * govern, are listed with their locations in: * 8 // * LICENSE and available at http://cern.ch/ << 8 // * http://cern.ch/geant4/license * 9 // * include a list of copyright holders. << 10 // * 9 // * * 11 // * Neither the authors of this software syst 10 // * Neither the authors of this software system, nor their employing * 12 // * institutes,nor the agencies providing fin 11 // * institutes,nor the agencies providing financial support for this * 13 // * work make any representation or warran 12 // * work make any representation or warranty, express or implied, * 14 // * regarding this software system or assum 13 // * regarding this software system or assume any liability for its * 15 // * use. Please see the license in the file << 14 // * use. * 16 // * for the full disclaimer and the limitatio << 17 // * 15 // * * 18 // * This code implementation is the result << 16 // * This code implementation is the intellectual property of the * 19 // * technical work of the GEANT4 collaboratio << 17 // * GEANT4 collaboration. * 20 // * By using, copying, modifying or distri << 18 // * By copying, distributing or modifying the Program (or any work * 21 // * any work based on the software) you ag << 19 // * based on the Program) you indicate your acceptance of this * 22 // * use in resulting scientific publicati << 20 // * statement, and all its terms. * 23 // * acceptance of all terms of the Geant4 Sof << 24 // ******************************************* 21 // ******************************************************************** 25 // 22 // >> 23 // >> 24 // $Id: G4Para.cc,v 1.22.2.1 2004/12/02 09:30:14 gcosmo Exp $ >> 25 // GEANT4 tag $Name: geant4-07-00-patch-01 $ >> 26 // >> 27 // class G4Para >> 28 // 26 // Implementation for G4Para class 29 // Implementation for G4Para class 27 // 30 // >> 31 // History: 28 // 21.03.95 P.Kent: Modified for `tolerant' ge 32 // 21.03.95 P.Kent: Modified for `tolerant' geom 29 // 31.10.96 V.Grichine: Modifications accordin 33 // 31.10.96 V.Grichine: Modifications according G4Box/Tubs before to commit 30 // 28.04.05 V.Grichine: new SurfaceNormal acco << 34 // 18.11.99 V.Grichine: kUndef was added to ESide 31 // 29.05.17 E.Tcherniaev: complete revision, s << 35 // 14.02.02 V.Grichine: bug fixed in Inside according to proposal of D.Wright 32 ////////////////////////////////////////////// << 36 // -------------------------------------------------------------------- 33 37 34 #include "G4Para.hh" 38 #include "G4Para.hh" 35 39 36 #if !defined(G4GEOM_USE_UPARA) << 37 << 38 #include "G4VoxelLimits.hh" 40 #include "G4VoxelLimits.hh" 39 #include "G4AffineTransform.hh" 41 #include "G4AffineTransform.hh" 40 #include "G4BoundingEnvelope.hh" << 41 #include "Randomize.hh" << 42 42 43 #include "G4VPVParameterisation.hh" 43 #include "G4VPVParameterisation.hh" 44 44 45 #include "G4VGraphicsScene.hh" 45 #include "G4VGraphicsScene.hh" >> 46 #include "G4Polyhedron.hh" >> 47 #include "G4NURBS.hh" >> 48 #include "G4NURBSbox.hh" 46 49 47 using namespace CLHEP; << 50 // Private enum: Not for external use >> 51 >> 52 enum ESide {kUndef,kPX,kMX,kPY,kMY,kPZ,kMZ}; 48 53 49 ////////////////////////////////////////////// << 54 // used internally for normal routine 50 // << 51 // Constructor - set & check half widths << 52 55 53 G4Para::G4Para(const G4String& pName, << 56 enum ENSide {kNZ,kNX,kNY}; 54 G4double pDx, G4double pD << 55 G4double pAlpha, G4double << 56 : G4CSGSolid(pName), halfCarTolerance(0.5*kC << 57 { << 58 SetAllParameters(pDx, pDy, pDz, pAlpha, pThe << 59 fRebuildPolyhedron = false; // default valu << 60 } << 61 57 62 ////////////////////////////////////////////// << 58 ///////////////////////////////////////////////////////////////////// 63 // 59 // 64 // Constructor - design of trapezoid based on << 60 // Constructor - check and set half-widths 65 61 66 G4Para::G4Para( const G4String& pName, << 62 void G4Para::SetAllParameters( G4double pDx, G4double pDy, G4double pDz, 67 const G4ThreeVector pt[8] ) << 63 G4double pAlpha, G4double pTheta, G4double pPhi ) 68 : G4CSGSolid(pName), halfCarTolerance(0.5*kC << 69 { 64 { 70 // Find dimensions and trigonometric values << 65 if (pDx>0&&pDy>0&&pDz>0) 71 // << 66 { 72 fDx = (pt[3].x() - pt[2].x())*0.5; << 67 fDx=pDx; 73 fDy = (pt[2].y() - pt[1].y())*0.5; << 68 fDy=pDy; 74 fDz = pt[7].z(); << 69 fDz=pDz; 75 CheckParameters(); // check dimensions << 70 fTalpha=std::tan(pAlpha); 76 << 71 fTthetaCphi=std::tan(pTheta)*std::cos(pPhi); 77 fTalpha = (pt[2].x() + pt[3].x() - pt[1].x() << 72 fTthetaSphi=std::tan(pTheta)*std::sin(pPhi); 78 fTthetaCphi = (pt[4].x() + fDy*fTalpha + fDx << 79 fTthetaSphi = (pt[4].y() + fDy)/fDz; << 80 MakePlanes(); << 81 << 82 // Recompute vertices << 83 // << 84 G4ThreeVector v[8]; << 85 G4double DyTalpha = fDy*fTalpha; << 86 G4double DzTthetaSphi = fDz*fTthetaSphi; << 87 G4double DzTthetaCphi = fDz*fTthetaCphi; << 88 v[0].set(-DzTthetaCphi-DyTalpha-fDx, -DzTthe << 89 v[1].set(-DzTthetaCphi-DyTalpha+fDx, -DzTthe << 90 v[2].set(-DzTthetaCphi+DyTalpha-fDx, -DzTthe << 91 v[3].set(-DzTthetaCphi+DyTalpha+fDx, -DzTthe << 92 v[4].set( DzTthetaCphi-DyTalpha-fDx, DzTthe << 93 v[5].set( DzTthetaCphi-DyTalpha+fDx, DzTthe << 94 v[6].set( DzTthetaCphi+DyTalpha-fDx, DzTthe << 95 v[7].set( DzTthetaCphi+DyTalpha+fDx, DzTthe << 96 << 97 // Compare with original vertices << 98 // << 99 for (G4int i=0; i<8; ++i) << 100 { << 101 G4double delx = std::abs(pt[i].x() - v[i]. << 102 G4double dely = std::abs(pt[i].y() - v[i]. << 103 G4double delz = std::abs(pt[i].z() - v[i]. << 104 G4double discrepancy = std::max(std::max(d << 105 if (discrepancy > 0.1*kCarTolerance) << 106 { << 107 std::ostringstream message; << 108 G4long oldprc = message.precision(16); << 109 message << "Invalid vertice coordinates << 110 << "\nVertix #" << i << ", discr << 111 << "\n original : " << pt[i] << 112 << "\n recomputed : " << v[i]; << 113 G4cout.precision(oldprc); << 114 G4Exception("G4Para::G4Para()", "GeomSol << 115 FatalException, message); << 116 << 117 } << 118 } 73 } >> 74 else >> 75 { >> 76 G4cerr << "ERROR - G4Para()::SetAllParameters(): " << GetName() << G4endl >> 77 << " Invalid dimensions ! - " >> 78 << pDx << ", " << pDy << ", " << pDz << G4endl; >> 79 G4Exception("G4Para::SetAllParameters()", "InvalidSetup", >> 80 FatalException, "Invalid Length Parameters."); >> 81 } >> 82 fCubicVolume = 0.; >> 83 fpPolyhedron = 0; 119 } 84 } 120 85 121 ////////////////////////////////////////////// << 86 /////////////////////////////////////////////////////////////////////////// 122 // << 123 // Fake default constructor - sets only member << 124 // for usage restri << 125 << 126 G4Para::G4Para( __void__& a ) << 127 : G4CSGSolid(a), halfCarTolerance(0.5*kCarTo << 128 { << 129 SetAllParameters(1., 1., 1., 0., 0., 0.); << 130 fRebuildPolyhedron = false; // default value << 131 } << 132 << 133 ////////////////////////////////////////////// << 134 // << 135 // Destructor << 136 << 137 G4Para::~G4Para() = default; << 138 << 139 ////////////////////////////////////////////// << 140 // << 141 // Copy constructor << 142 << 143 G4Para::G4Para(const G4Para& rhs) << 144 : G4CSGSolid(rhs), halfCarTolerance(rhs.half << 145 fDx(rhs.fDx), fDy(rhs.fDy), fDz(rhs.fDz), << 146 fTthetaCphi(rhs.fTthetaCphi),fTthetaSphi(r << 147 { << 148 for (G4int i=0; i<4; ++i) { fPlanes[i] = rhs << 149 } << 150 << 151 ////////////////////////////////////////////// << 152 // << 153 // Assignment operator << 154 << 155 G4Para& G4Para::operator = (const G4Para& rhs) << 156 { << 157 // Check assignment to self << 158 // << 159 if (this == &rhs) { return *this; } << 160 << 161 // Copy base class data << 162 // << 163 G4CSGSolid::operator=(rhs); << 164 << 165 // Copy data << 166 // << 167 halfCarTolerance = rhs.halfCarTolerance; << 168 fDx = rhs.fDx; << 169 fDy = rhs.fDy; << 170 fDz = rhs.fDz; << 171 fTalpha = rhs.fTalpha; << 172 fTthetaCphi = rhs.fTthetaCphi; << 173 fTthetaSphi = rhs.fTthetaSphi; << 174 for (G4int i=0; i<4; ++i) { fPlanes[i] = rh << 175 << 176 return *this; << 177 } << 178 << 179 ////////////////////////////////////////////// << 180 // << 181 // Set all parameters, as for constructor - se << 182 << 183 void G4Para::SetAllParameters(G4double pDx, G4 << 184 G4double pAlpha, << 185 { << 186 // Reset data of the base class << 187 fCubicVolume = 0; << 188 fSurfaceArea = 0; << 189 fRebuildPolyhedron = true; << 190 << 191 // Set parameters << 192 fDx = pDx; << 193 fDy = pDy; << 194 fDz = pDz; << 195 fTalpha = std::tan(pAlpha); << 196 fTthetaCphi = std::tan(pTheta)*std::cos(pPhi << 197 fTthetaSphi = std::tan(pTheta)*std::sin(pPhi << 198 << 199 CheckParameters(); << 200 MakePlanes(); << 201 } << 202 << 203 ////////////////////////////////////////////// << 204 // 87 // 205 // Check dimensions << 206 88 207 void G4Para::CheckParameters() << 89 G4Para::G4Para(const G4String& pName, >> 90 G4double pDx, G4double pDy, G4double pDz, >> 91 G4double pAlpha, G4double pTheta, G4double pPhi) >> 92 : G4CSGSolid(pName) 208 { 93 { 209 if (fDx < 2*kCarTolerance || << 94 if (pDx>0&&pDy>0&&pDz>0) 210 fDy < 2*kCarTolerance || << 95 { 211 fDz < 2*kCarTolerance) << 96 SetAllParameters( pDx, pDy, pDz, pAlpha, pTheta, pPhi); 212 { << 97 } 213 std::ostringstream message; << 98 else 214 message << "Invalid (too small or negative << 99 { 215 << GetName() << 100 G4cerr << "ERROR - G4Para()::G4Para(): " << GetName() << G4endl 216 << "\n X - " << fDx << 101 << " Invalid dimensions ! - " 217 << "\n Y - " << fDy << 102 << pDx << ", " << pDy << ", " << pDz << G4endl; 218 << "\n Z - " << fDz; << 103 G4Exception("G4Para::G4Para()", "InvalidSetup", 219 G4Exception("G4Para::CheckParameters()", " << 104 FatalException, "Invalid Length Parameters."); 220 FatalException, message); << 221 } 105 } 222 } 106 } 223 107 224 ////////////////////////////////////////////// << 108 //////////////////////////////////////////////////////////////////////// 225 // 109 // 226 // Set side planes << 110 // Constructor - Design of trapezoid based on 8 G4ThreeVector parameters, >> 111 // which are its vertices. Checking of planarity with preparation of >> 112 // fPlanes[] and than calculation of other members 227 113 228 void G4Para::MakePlanes() << 114 G4Para::G4Para( const G4String& pName, >> 115 const G4ThreeVector pt[8] ) >> 116 : G4CSGSolid(pName) 229 { 117 { 230 G4ThreeVector vx(1, 0, 0); << 118 if ( pt[0].z()<0 && pt[0].z()==pt[1].z() && pt[0].z()==pt[2].z() && 231 G4ThreeVector vy(fTalpha, 1, 0); << 119 pt[0].z()==pt[3].z() && pt[4].z()>0 && pt[4].z()==pt[5].z() && 232 G4ThreeVector vz(fTthetaCphi, fTthetaSphi, 1 << 120 pt[4].z()==pt[6].z() && pt[4].z()==pt[7].z() && 233 << 121 (pt[0].z()+pt[4].z())==0 && 234 // Set -Y & +Y planes << 122 pt[0].y()==pt[1].y() && pt[2].y()==pt[3].y() && 235 // << 123 pt[4].y()==pt[5].y() && pt[6].y()==pt[7].y() && 236 G4ThreeVector ynorm = (vx.cross(vz)).unit(); << 124 (pt[0].y()+pt[2].y()+pt[4].y()+pt[6].y())==0 ) >> 125 { >> 126 fDz = (pt[7]).z() ; >> 127 >> 128 fDy = ((pt[2]).y()-(pt[1]).y())*0.5 ; >> 129 fDx = ((pt[1]).x()-(pt[0]).x())*0.5 ; >> 130 fDx = ((pt[3]).x()-(pt[2]).x())*0.5 ; >> 131 fTalpha = ((pt[2]).x()+(pt[3]).x()-(pt[1]).x()-(pt[0]).x())*0.25/fDy ; >> 132 >> 133 // fDy = ((pt[6]).y()-(pt[5]).y())*0.5 ; >> 134 // fDx = ((pt[5]).x()-(pt[4]).x())*0.5 ; >> 135 // fDx = ((pt[7]).x()-(pt[6]).x())*0.5 ; >> 136 // fTalpha = ((pt[6]).x()+(pt[7]).x()-(pt[5]).x()-(pt[4]).x())*0.25/fDy ; 237 137 238 fPlanes[0].a = 0.; << 138 fTthetaCphi = ((pt[4]).x()+fDy*fTalpha+fDx)/fDz ; 239 fPlanes[0].b = ynorm.y(); << 139 fTthetaSphi = ((pt[4]).y()+fDy)/fDz ; 240 fPlanes[0].c = ynorm.z(); << 241 fPlanes[0].d = fPlanes[0].b*fDy; // point (0 << 242 << 243 fPlanes[1].a = 0.; << 244 fPlanes[1].b = -fPlanes[0].b; << 245 fPlanes[1].c = -fPlanes[0].c; << 246 fPlanes[1].d = fPlanes[0].d; << 247 << 248 // Set -X & +X planes << 249 // << 250 G4ThreeVector xnorm = (vz.cross(vy)).unit(); << 251 << 252 fPlanes[2].a = xnorm.x(); << 253 fPlanes[2].b = xnorm.y(); << 254 fPlanes[2].c = xnorm.z(); << 255 fPlanes[2].d = fPlanes[2].a*fDx; // point (f << 256 << 257 fPlanes[3].a = -fPlanes[2].a; << 258 fPlanes[3].b = -fPlanes[2].b; << 259 fPlanes[3].c = -fPlanes[2].c; << 260 fPlanes[3].d = fPlanes[2].d; << 261 } << 262 << 263 ////////////////////////////////////////////// << 264 // << 265 // Get volume << 266 << 267 G4double G4Para::GetCubicVolume() << 268 { << 269 // It is like G4Box, since para transformati << 270 if (fCubicVolume == 0) << 271 { << 272 fCubicVolume = 8*fDx*fDy*fDz; << 273 } 140 } 274 return fCubicVolume; << 141 else >> 142 { >> 143 G4cerr << "ERROR - G4Para()::G4Para(): " << GetName() << G4endl >> 144 << " Invalid dimensions !" << G4endl; >> 145 G4Exception("G4Para::G4Para()", "InvalidSetup", >> 146 FatalException, "Invalid vertice coordinates."); >> 147 } 275 } 148 } 276 149 277 ////////////////////////////////////////////// 150 ////////////////////////////////////////////////////////////////////////// 278 // 151 // 279 // Get surface area << 280 152 281 G4double G4Para::GetSurfaceArea() << 153 G4Para::~G4Para() 282 { 154 { 283 if(fSurfaceArea == 0) << 284 { << 285 G4ThreeVector vx(fDx, 0, 0); << 286 G4ThreeVector vy(fDy*fTalpha, fDy, 0); << 287 G4ThreeVector vz(fDz*fTthetaCphi, fDz*fTth << 288 << 289 G4double sxy = fDx*fDy; // (vx.cross(vy)). << 290 G4double sxz = (vx.cross(vz)).mag(); << 291 G4double syz = (vy.cross(vz)).mag(); << 292 << 293 fSurfaceArea = 8*(sxy+sxz+syz); << 294 } << 295 return fSurfaceArea; << 296 } 155 } 297 156 298 ////////////////////////////////////////////// 157 ////////////////////////////////////////////////////////////////////////// 299 // 158 // 300 // Dispatch to parameterisation for replicatio 159 // Dispatch to parameterisation for replication mechanism dimension 301 // computation & modification << 160 // computation & modification. 302 161 303 void G4Para::ComputeDimensions( G4VPVPara 162 void G4Para::ComputeDimensions( G4VPVParameterisation* p, 304 const G4int n, 163 const G4int n, 305 const G4VPhysi 164 const G4VPhysicalVolume* pRep ) 306 { 165 { 307 p->ComputeDimensions(*this,n,pRep); 166 p->ComputeDimensions(*this,n,pRep); 308 } 167 } 309 168 310 ////////////////////////////////////////////// << 311 // << 312 // Get bounding box << 313 169 314 void G4Para::BoundingLimits(G4ThreeVector& pMi << 170 ////////////////////////////////////////////////////////////// 315 { << 316 G4double dz = GetZHalfLength(); << 317 G4double dx = GetXHalfLength(); << 318 G4double dy = GetYHalfLength(); << 319 << 320 G4double x0 = dz*fTthetaCphi; << 321 G4double x1 = dy*GetTanAlpha(); << 322 G4double xmin = << 323 std::min( << 324 std::min( << 325 std::min(-x0-x1-dx,-x0+x1-dx),x0-x1-dx),x0 << 326 G4double xmax = << 327 std::max( << 328 std::max( << 329 std::max(-x0-x1+dx,-x0+x1+dx),x0-x1+dx),x0 << 330 << 331 G4double y0 = dz*fTthetaSphi; << 332 G4double ymin = std::min(-y0-dy,y0-dy); << 333 G4double ymax = std::max(-y0+dy,y0+dy); << 334 << 335 pMin.set(xmin,ymin,-dz); << 336 pMax.set(xmax,ymax, dz); << 337 << 338 // Check correctness of the bounding box << 339 // << 340 if (pMin.x() >= pMax.x() || pMin.y() >= pMax << 341 { << 342 std::ostringstream message; << 343 message << "Bad bounding box (min >= max) << 344 << GetName() << " !" << 345 << "\npMin = " << pMin << 346 << "\npMax = " << pMax; << 347 G4Exception("G4Para::BoundingLimits()", "G << 348 JustWarning, message); << 349 DumpInfo(); << 350 } << 351 } << 352 << 353 ////////////////////////////////////////////// << 354 // 171 // 355 // Calculate extent under transform and specif 172 // Calculate extent under transform and specified limit 356 173 357 G4bool G4Para::CalculateExtent( const EAxis pA 174 G4bool G4Para::CalculateExtent( const EAxis pAxis, 358 const G4VoxelL 175 const G4VoxelLimits& pVoxelLimit, 359 const G4Affine 176 const G4AffineTransform& pTransform, 360 G4double& 177 G4double& pMin, G4double& pMax ) const 361 { 178 { 362 G4ThreeVector bmin, bmax; << 179 G4bool flag; 363 G4bool exist; << 364 180 365 // Check bounding box (bbox) << 181 if (!pTransform.IsRotated()) 366 // << 182 { 367 BoundingLimits(bmin,bmax); << 183 // Special case handling for unrotated trapezoids 368 G4BoundingEnvelope bbox(bmin,bmax); << 184 // Compute z/x/y/ mins and maxs respecting limits, with early returns 369 #ifdef G4BBOX_EXTENT << 185 // if outside limits. Then switch() on pAxis 370 return bbox.CalculateExtent(pAxis,pVoxelLimi << 186 371 #endif << 187 G4int i ; 372 if (bbox.BoundingBoxVsVoxelLimits(pAxis,pVox << 188 G4double xoffset,xMin,xMax; 373 { << 189 G4double yoffset,yMin,yMax; 374 return exist = pMin < pMax; << 190 G4double zoffset,zMin,zMax; 375 } << 191 G4double temp[8] ; // some points for intersection with zMin/zMax >> 192 >> 193 xoffset=pTransform.NetTranslation().x(); >> 194 yoffset=pTransform.NetTranslation().y(); >> 195 zoffset=pTransform.NetTranslation().z(); >> 196 >> 197 G4ThreeVector pt[8]; // vertices after translation >> 198 pt[0]=G4ThreeVector(xoffset-fDz*fTthetaCphi-fDy*fTalpha-fDx, >> 199 yoffset-fDz*fTthetaSphi-fDy,zoffset-fDz); >> 200 pt[1]=G4ThreeVector(xoffset-fDz*fTthetaCphi-fDy*fTalpha+fDx, >> 201 yoffset-fDz*fTthetaSphi-fDy,zoffset-fDz); >> 202 pt[2]=G4ThreeVector(xoffset-fDz*fTthetaCphi+fDy*fTalpha-fDx, >> 203 yoffset-fDz*fTthetaSphi+fDy,zoffset-fDz); >> 204 pt[3]=G4ThreeVector(xoffset-fDz*fTthetaCphi+fDy*fTalpha+fDx, >> 205 yoffset-fDz*fTthetaSphi+fDy,zoffset-fDz); >> 206 pt[4]=G4ThreeVector(xoffset+fDz*fTthetaCphi-fDy*fTalpha-fDx, >> 207 yoffset+fDz*fTthetaSphi-fDy,zoffset+fDz); >> 208 pt[5]=G4ThreeVector(xoffset+fDz*fTthetaCphi-fDy*fTalpha+fDx, >> 209 yoffset+fDz*fTthetaSphi-fDy,zoffset+fDz); >> 210 pt[6]=G4ThreeVector(xoffset+fDz*fTthetaCphi+fDy*fTalpha-fDx, >> 211 yoffset+fDz*fTthetaSphi+fDy,zoffset+fDz); >> 212 pt[7]=G4ThreeVector(xoffset+fDz*fTthetaCphi+fDy*fTalpha+fDx, >> 213 yoffset+fDz*fTthetaSphi+fDy,zoffset+fDz); >> 214 zMin=zoffset-fDz; >> 215 zMax=zoffset+fDz; >> 216 if ( pVoxelLimit.IsZLimited() ) >> 217 { >> 218 if ( (zMin>pVoxelLimit.GetMaxZExtent()+kCarTolerance) >> 219 || (zMax<pVoxelLimit.GetMinZExtent()-kCarTolerance) ) >> 220 { >> 221 return false; >> 222 } >> 223 else >> 224 { >> 225 if (zMin<pVoxelLimit.GetMinZExtent()) >> 226 { >> 227 zMin=pVoxelLimit.GetMinZExtent(); >> 228 } >> 229 if (zMax>pVoxelLimit.GetMaxZExtent()) >> 230 { >> 231 zMax=pVoxelLimit.GetMaxZExtent(); >> 232 } >> 233 } >> 234 } 376 235 377 // Set bounding envelope (benv) and calculat << 236 temp[0] = pt[0].y()+(pt[4].y()-pt[0].y()) 378 // << 237 *(zMin-pt[0].z())/(pt[4].z()-pt[0].z()) ; 379 G4double dz = GetZHalfLength(); << 238 temp[1] = pt[0].y()+(pt[4].y()-pt[0].y()) 380 G4double dx = GetXHalfLength(); << 239 *(zMax-pt[0].z())/(pt[4].z()-pt[0].z()) ; 381 G4double dy = GetYHalfLength(); << 240 temp[2] = pt[2].y()+(pt[6].y()-pt[2].y()) >> 241 *(zMin-pt[2].z())/(pt[6].z()-pt[2].z()) ; >> 242 temp[3] = pt[2].y()+(pt[6].y()-pt[2].y()) >> 243 *(zMax-pt[2].z())/(pt[6].z()-pt[2].z()) ; >> 244 yMax = yoffset - std::fabs(fDz*fTthetaSphi) - fDy - fDy ; >> 245 yMin = -yMax ; >> 246 for(i=0;i<4;i++) >> 247 { >> 248 if(temp[i] > yMax) yMax = temp[i] ; >> 249 if(temp[i] < yMin) yMin = temp[i] ; >> 250 } >> 251 >> 252 if (pVoxelLimit.IsYLimited()) >> 253 { >> 254 if ( (yMin>pVoxelLimit.GetMaxYExtent()+kCarTolerance) >> 255 || (yMax<pVoxelLimit.GetMinYExtent()-kCarTolerance) ) >> 256 { >> 257 return false; >> 258 } >> 259 else >> 260 { >> 261 if (yMin<pVoxelLimit.GetMinYExtent()) >> 262 { >> 263 yMin=pVoxelLimit.GetMinYExtent(); >> 264 } >> 265 if (yMax>pVoxelLimit.GetMaxYExtent()) >> 266 { >> 267 yMax=pVoxelLimit.GetMaxYExtent(); >> 268 } >> 269 } >> 270 } 382 271 383 G4double x0 = dz*fTthetaCphi; << 272 temp[0] = pt[0].x()+(pt[4].x()-pt[0].x()) 384 G4double x1 = dy*GetTanAlpha(); << 273 *(zMin-pt[0].z())/(pt[4].z()-pt[0].z()) ; 385 G4double y0 = dz*fTthetaSphi; << 274 temp[1] = pt[0].x()+(pt[4].x()-pt[0].x()) >> 275 *(zMax-pt[0].z())/(pt[4].z()-pt[0].z()) ; >> 276 temp[2] = pt[2].x()+(pt[6].x()-pt[2].x()) >> 277 *(zMin-pt[2].z())/(pt[6].z()-pt[2].z()) ; >> 278 temp[3] = pt[2].x()+(pt[6].x()-pt[2].x()) >> 279 *(zMax-pt[2].z())/(pt[6].z()-pt[2].z()) ; >> 280 temp[4] = pt[3].x()+(pt[7].x()-pt[3].x()) >> 281 *(zMin-pt[3].z())/(pt[7].z()-pt[3].z()) ; >> 282 temp[5] = pt[3].x()+(pt[7].x()-pt[3].x()) >> 283 *(zMax-pt[3].z())/(pt[7].z()-pt[3].z()) ; >> 284 temp[6] = pt[1].x()+(pt[5].x()-pt[1].x()) >> 285 *(zMin-pt[1].z())/(pt[5].z()-pt[1].z()) ; >> 286 temp[7] = pt[1].x()+(pt[5].x()-pt[1].x()) >> 287 *(zMax-pt[1].z())/(pt[5].z()-pt[1].z()) ; >> 288 >> 289 xMax = xoffset - std::fabs(fDz*fTthetaCphi) - fDx - fDx -fDx - fDx; >> 290 xMin = -xMax ; >> 291 for(i=0;i<8;i++) >> 292 { >> 293 if(temp[i] > xMax) xMax = temp[i] ; >> 294 if(temp[i] < xMin) xMin = temp[i] ; >> 295 } >> 296 // xMax/Min = f(yMax/Min) ? >> 297 if (pVoxelLimit.IsXLimited()) >> 298 { >> 299 if ( (xMin>pVoxelLimit.GetMaxXExtent()+kCarTolerance) >> 300 || (xMax<pVoxelLimit.GetMinXExtent()-kCarTolerance) ) >> 301 { >> 302 return false; >> 303 } >> 304 else >> 305 { >> 306 if (xMin<pVoxelLimit.GetMinXExtent()) >> 307 { >> 308 xMin=pVoxelLimit.GetMinXExtent(); >> 309 } >> 310 if (xMax>pVoxelLimit.GetMaxXExtent()) >> 311 { >> 312 xMax=pVoxelLimit.GetMaxXExtent(); >> 313 } >> 314 } >> 315 } >> 316 >> 317 switch (pAxis) >> 318 { >> 319 case kXAxis: >> 320 pMin=xMin; >> 321 pMax=xMax; >> 322 break; >> 323 case kYAxis: >> 324 pMin=yMin; >> 325 pMax=yMax; >> 326 break; >> 327 case kZAxis: >> 328 pMin=zMin; >> 329 pMax=zMax; >> 330 break; >> 331 default: >> 332 break; >> 333 } 386 334 387 G4ThreeVectorList baseA(4), baseB(4); << 335 pMin-=kCarTolerance; 388 baseA[0].set(-x0-x1-dx,-y0-dy,-dz); << 336 pMax+=kCarTolerance; 389 baseA[1].set(-x0-x1+dx,-y0-dy,-dz); << 337 flag = true; 390 baseA[2].set(-x0+x1+dx,-y0+dy,-dz); << 338 } 391 baseA[3].set(-x0+x1-dx,-y0+dy,-dz); << 339 else >> 340 { >> 341 // General rotated case - create and clip mesh to boundaries 392 342 393 baseB[0].set(+x0-x1-dx, y0-dy, dz); << 343 G4bool existsAfterClip=false; 394 baseB[1].set(+x0-x1+dx, y0-dy, dz); << 344 G4ThreeVectorList *vertices; 395 baseB[2].set(+x0+x1+dx, y0+dy, dz); << 396 baseB[3].set(+x0+x1-dx, y0+dy, dz); << 397 345 398 std::vector<const G4ThreeVectorList *> polyg << 346 pMin=+kInfinity; 399 polygons[0] = &baseA; << 347 pMax=-kInfinity; 400 polygons[1] = &baseB; << 401 348 402 G4BoundingEnvelope benv(bmin,bmax,polygons); << 349 // Calculate rotated vertex coordinates 403 exist = benv.CalculateExtent(pAxis,pVoxelLim << 350 404 return exist; << 351 vertices=CreateRotatedVertices(pTransform); >> 352 ClipCrossSection(vertices,0,pVoxelLimit,pAxis,pMin,pMax); >> 353 ClipCrossSection(vertices,4,pVoxelLimit,pAxis,pMin,pMax); >> 354 ClipBetweenSections(vertices,0,pVoxelLimit,pAxis,pMin,pMax); >> 355 >> 356 if (pMin!=kInfinity||pMax!=-kInfinity) >> 357 { >> 358 existsAfterClip=true; >> 359 >> 360 // Add 2*tolerance to avoid precision troubles >> 361 // >> 362 pMin-=kCarTolerance; >> 363 pMax+=kCarTolerance; >> 364 } >> 365 else >> 366 { >> 367 // Check for case where completely enveloping clipping volume >> 368 // If point inside then we are confident that the solid completely >> 369 // envelopes the clipping volume. Hence set min/max extents according >> 370 // to clipping volume extents along the specified axis. >> 371 >> 372 G4ThreeVector clipCentre( >> 373 (pVoxelLimit.GetMinXExtent()+pVoxelLimit.GetMaxXExtent())*0.5, >> 374 (pVoxelLimit.GetMinYExtent()+pVoxelLimit.GetMaxYExtent())*0.5, >> 375 (pVoxelLimit.GetMinZExtent()+pVoxelLimit.GetMaxZExtent())*0.5); >> 376 >> 377 if (Inside(pTransform.Inverse().TransformPoint(clipCentre))!=kOutside) >> 378 { >> 379 existsAfterClip=true; >> 380 pMin=pVoxelLimit.GetMinExtent(pAxis); >> 381 pMax=pVoxelLimit.GetMaxExtent(pAxis); >> 382 } >> 383 } >> 384 delete vertices ; // 'new' in the function called >> 385 flag = existsAfterClip ; >> 386 } >> 387 return flag; 405 } 388 } 406 389 407 ////////////////////////////////////////////// << 390 ///////////////////////////////////////////////////////////////////////////// 408 // << 409 // Determine where is point p, inside/on_surfa << 410 // 391 // >> 392 // Check in p is inside/on surface/outside solid 411 393 412 EInside G4Para::Inside( const G4ThreeVector& p 394 EInside G4Para::Inside( const G4ThreeVector& p ) const 413 { 395 { 414 G4double xx = fPlanes[2].a*p.x()+fPlanes[2]. << 396 G4double xt, yt, yt1; 415 G4double dx = std::abs(xx) + fPlanes[2].d; << 397 EInside in = kOutside; >> 398 >> 399 yt1 = p.y() - fTthetaSphi*p.z(); >> 400 yt = std::fabs(yt1) ; 416 401 417 G4double yy = fPlanes[0].b*p.y()+fPlanes[0]. << 402 // xt = std::fabs( p.x() - fTthetaCphi*p.z() - fTalpha*yt ); 418 G4double dy = std::abs(yy) + fPlanes[0].d; << 419 G4double dxy = std::max(dx,dy); << 420 403 421 G4double dz = std::abs(p.z())-fDz; << 404 xt = std::fabs( p.x() - fTthetaCphi*p.z() - fTalpha*yt1 ); 422 G4double dist = std::max(dxy,dz); << 423 405 424 if (dist > halfCarTolerance) return kOutside << 406 if ( std::fabs( p.z() ) <= fDz - kCarTolerance*0.5) 425 return (dist > -halfCarTolerance) ? kSurface << 407 { >> 408 if (yt <= fDy - kCarTolerance*0.5) >> 409 { >> 410 if ( xt <= fDx - kCarTolerance*0.5 ) in = kInside; >> 411 else if ( xt <= fDx + kCarTolerance*0.5 ) in = kSurface; >> 412 } >> 413 else if ( yt <= fDy + kCarTolerance*0.5) >> 414 { >> 415 if ( xt <= fDx + kCarTolerance*0.5 ) in = kSurface; >> 416 } >> 417 } >> 418 else if ( std::fabs(p.z()) <= fDz + kCarTolerance*0.5 ) >> 419 { >> 420 if ( yt <= fDy + kCarTolerance*0.5) >> 421 { >> 422 if ( xt <= fDx + kCarTolerance*0.5 ) in = kSurface; >> 423 } >> 424 } >> 425 return in; 426 } 426 } 427 427 428 ////////////////////////////////////////////// << 428 /////////////////////////////////////////////////////////////////////////// 429 // 429 // 430 // Determine side where point is, and return c << 430 // Calculate side nearest to p, and return normal >> 431 // If 2+ sides equidistant, first side's normal returned (arbitrarily) 431 432 432 G4ThreeVector G4Para::SurfaceNormal( const G4T 433 G4ThreeVector G4Para::SurfaceNormal( const G4ThreeVector& p ) const 433 { 434 { 434 G4int nsurf = 0; // number of surfaces where << 435 ENSide side; >> 436 G4ThreeVector norm; >> 437 G4double distx,disty,distz; >> 438 G4double newpx,newpy,xshift; >> 439 G4double calpha,salpha; // Sin/Cos(alpha) - needed to recalc G4Parameter >> 440 G4double tntheta,cosntheta; // tan and cos of normal's theta component >> 441 G4double ycomp; 435 442 436 // Check Z faces << 443 newpx=p.x()-fTthetaCphi*p.z(); 437 // << 444 newpy=p.y()-fTthetaSphi*p.z(); 438 G4double nz = 0; << 439 G4double dz = std::abs(p.z()) - fDz; << 440 if (std::abs(dz) <= halfCarTolerance) << 441 { << 442 nz = (p.z() < 0) ? -1 : 1; << 443 ++nsurf; << 444 } << 445 445 446 // Check Y faces << 446 calpha=1/std::sqrt(1+fTalpha*fTalpha); 447 // << 447 if (fTalpha) 448 G4double ny = 0; << 449 G4double yy = fPlanes[0].b*p.y()+fPlanes[0]. << 450 if (std::abs(fPlanes[0].d + yy) <= halfCarTo << 451 { 448 { 452 ny = fPlanes[0].b; << 449 salpha=-calpha/fTalpha; // NOTE: actually use MINUS std::sin(alpha) 453 nz += fPlanes[0].c; << 454 ++nsurf; << 455 } 450 } 456 else if (std::abs(fPlanes[1].d - yy) <= half << 451 else 457 { 452 { 458 ny = fPlanes[1].b; << 453 salpha=0; 459 nz += fPlanes[1].c; << 460 ++nsurf; << 461 } 454 } 462 455 463 // Check X faces << 456 xshift=newpx*calpha+newpy*salpha; 464 // << 457 465 G4double nx = 0; << 458 distx=std::fabs(std::fabs(xshift)-fDx*calpha); 466 G4double xx = fPlanes[2].a*p.x()+fPlanes[2]. << 459 disty=std::fabs(std::fabs(newpy)-fDy); 467 if (std::abs(fPlanes[2].d + xx) <= halfCarTo << 460 distz=std::fabs(std::fabs(p.z())-fDz); 468 { << 461 469 nx = fPlanes[2].a; << 462 if (distx<disty) 470 ny += fPlanes[2].b; << 471 nz += fPlanes[2].c; << 472 ++nsurf; << 473 } << 474 else if (std::abs(fPlanes[3].d - xx) <= half << 475 { 463 { 476 nx = fPlanes[3].a; << 464 if (distx<distz) side=kNX; 477 ny += fPlanes[3].b; << 465 else side=kNZ; 478 nz += fPlanes[3].c; << 479 ++nsurf; << 480 } 466 } 481 << 482 // Return normal << 483 // << 484 if (nsurf == 1) return {nx,ny,nz}; << 485 else if (nsurf != 0) return G4ThreeVector(nx << 486 else 467 else 487 { 468 { 488 // Point is not on the surface << 469 if (disty<distz) side=kNY; 489 // << 470 else side=kNZ; 490 #ifdef G4CSGDEBUG << 491 std::ostringstream message; << 492 G4int oldprc = message.precision(16); << 493 message << "Point p is not on surface (!?) << 494 << GetName() << G4endl; << 495 message << "Position:\n"; << 496 message << " p.x() = " << p.x()/mm << " << 497 message << " p.y() = " << p.y()/mm << " << 498 message << " p.z() = " << p.z()/mm << " << 499 G4cout.precision(oldprc) ; << 500 G4Exception("G4Para::SurfaceNormal(p)", "G << 501 JustWarning, message ); << 502 DumpInfo(); << 503 #endif << 504 return ApproxSurfaceNormal(p); << 505 } 471 } 506 } << 507 472 508 ////////////////////////////////////////////// << 473 switch (side) 509 // << 510 // Algorithm for SurfaceNormal() following the << 511 // for points not on the surface << 512 << 513 G4ThreeVector G4Para::ApproxSurfaceNormal( con << 514 { << 515 G4double dist = -DBL_MAX; << 516 G4int iside = 0; << 517 for (G4int i=0; i<4; ++i) << 518 { 474 { 519 G4double d = fPlanes[i].a*p.x() + << 475 case kNX: 520 fPlanes[i].b*p.y() + << 476 tntheta=fTthetaCphi*calpha+fTthetaSphi*salpha; 521 fPlanes[i].c*p.z() + fPlanes[ << 477 if (xshift<0) 522 if (d > dist) { dist = d; iside = i; } << 478 { >> 479 cosntheta=-1/std::sqrt(1+tntheta*tntheta); >> 480 } >> 481 else >> 482 { >> 483 cosntheta=1/std::sqrt(1+tntheta*tntheta); >> 484 } >> 485 norm=G4ThreeVector(calpha*cosntheta,salpha*cosntheta,-tntheta*cosntheta); >> 486 break; >> 487 case kNY: >> 488 if (newpy<0) >> 489 { >> 490 ycomp=-1/std::sqrt(1+fTthetaSphi*fTthetaSphi); >> 491 } >> 492 else >> 493 { >> 494 ycomp=1/std::sqrt(1+fTthetaSphi*fTthetaSphi); >> 495 } >> 496 norm=G4ThreeVector(0,ycomp,-fTthetaSphi*ycomp); >> 497 break; >> 498 case kNZ: // Closest to Z >> 499 if (p.z()>=0) >> 500 { >> 501 norm=G4ThreeVector(0,0,1); >> 502 } >> 503 else >> 504 { >> 505 norm=G4ThreeVector(0,0,-1); >> 506 } >> 507 break; 523 } 508 } 524 << 509 return norm; 525 G4double distz = std::abs(p.z()) - fDz; << 526 if (dist > distz) << 527 return { fPlanes[iside].a, fPlanes[iside]. << 528 else << 529 return { 0, 0, (G4double)((p.z() < 0) ? -1 << 530 } 510 } 531 511 532 ////////////////////////////////////////////// << 512 ////////////////////////////////////////////////////////////////////////////// 533 // 513 // 534 // Calculate distance to shape from outside 514 // Calculate distance to shape from outside 535 // - return kInfinity if no intersection << 515 // - return kInfinity if no intersection 536 << 516 // 537 G4double G4Para::DistanceToIn(const G4ThreeVec << 517 // ALGORITHM: 538 const G4ThreeVec << 518 // For each component, calculate pair of minimum and maximum intersection 539 { << 519 // values for which the particle is in the extent of the shape 540 // Z intersections << 520 // - The smallest (MAX minimum) allowed distance of the pairs is intersect >> 521 // - Z plane intersectin uses tolerance >> 522 // - XZ YZ planes use logic & *SLIGHTLY INCORRECT* tolerance >> 523 // (this saves at least 1 sqrt, 1 multiply and 1 divide... in applicable >> 524 // cases) >> 525 // - Note: XZ and YZ planes each divide space into four regions, >> 526 // characterised by ss1 ss2 >> 527 >> 528 G4double G4Para::DistanceToIn( const G4ThreeVector& p, >> 529 const G4ThreeVector& v ) const >> 530 { >> 531 G4double snxt; // snxt = default return value >> 532 G4double smin,smax; >> 533 G4double tmin,tmax; >> 534 G4double yt,vy,xt,vx; >> 535 G4double max; 541 // 536 // 542 if ((std::abs(p.z()) - fDz) >= -halfCarToler << 537 // Z Intersection range 543 return kInfinity; << 544 G4double invz = (-v.z() == 0) ? DBL_MAX : -1 << 545 G4double dz = (invz < 0) ? fDz : -fDz; << 546 G4double tzmin = (p.z() + dz)*invz; << 547 G4double tzmax = (p.z() - dz)*invz; << 548 << 549 // Y intersections << 550 // 538 // 551 G4double tmin0 = tzmin, tmax0 = tzmax; << 539 if (v.z()>0) 552 G4double cos0 = fPlanes[0].b*v.y() + fPlanes << 540 { 553 G4double disy = fPlanes[0].b*p.y() + fPlanes << 541 max=fDz-p.z(); 554 G4double dis0 = fPlanes[0].d + disy; << 542 if (max>kCarTolerance*0.5) 555 if (dis0 >= -halfCarTolerance) << 543 { >> 544 smax=max/v.z(); >> 545 smin=(-fDz-p.z())/v.z(); >> 546 } >> 547 else >> 548 { >> 549 return snxt=kInfinity; >> 550 } >> 551 } >> 552 else if (v.z()<0) 556 { 553 { 557 if (cos0 >= 0) return kInfinity; << 554 max=-fDz-p.z(); 558 G4double tmp = -dis0/cos0; << 555 if (max<-kCarTolerance*0.5) 559 if (tmin0 < tmp) tmin0 = tmp; << 556 { >> 557 smax=max/v.z(); >> 558 smin=(fDz-p.z())/v.z(); >> 559 } >> 560 else >> 561 { >> 562 return snxt=kInfinity; >> 563 } 560 } 564 } 561 else if (cos0 > 0) << 565 else 562 { 566 { 563 G4double tmp = -dis0/cos0; << 567 if (std::fabs(p.z())<=fDz) // Inside 564 if (tmax0 > tmp) tmax0 = tmp; << 568 { >> 569 smin=0; >> 570 smax=kInfinity; >> 571 } >> 572 else >> 573 { >> 574 return snxt=kInfinity; >> 575 } 565 } 576 } >> 577 >> 578 // >> 579 // Y G4Parallel planes intersection >> 580 // >> 581 >> 582 yt=p.y()-fTthetaSphi*p.z(); >> 583 vy=v.y()-fTthetaSphi*v.z(); 566 584 567 G4double tmin1 = tmin0, tmax1 = tmax0; << 585 if (vy>0) 568 G4double cos1 = -cos0; << 569 G4double dis1 = fPlanes[1].d - disy; << 570 if (dis1 >= -halfCarTolerance) << 571 { 586 { 572 if (cos1 >= 0) return kInfinity; << 587 max=fDy-yt; 573 G4double tmp = -dis1/cos1; << 588 if (max>kCarTolerance*0.5) 574 if (tmin1 < tmp) tmin1 = tmp; << 589 { >> 590 tmax=max/vy; >> 591 tmin=(-fDy-yt)/vy; >> 592 } >> 593 else >> 594 { >> 595 return snxt=kInfinity; >> 596 } 575 } 597 } 576 else if (cos1 > 0) << 598 else if (vy<0) 577 { 599 { 578 G4double tmp = -dis1/cos1; << 600 max=-fDy-yt; 579 if (tmax1 > tmp) tmax1 = tmp; << 601 if (max<-kCarTolerance*0.5) >> 602 { >> 603 tmax=max/vy; >> 604 tmin=(fDy-yt)/vy; >> 605 } >> 606 else >> 607 { >> 608 return snxt=kInfinity; >> 609 } >> 610 } >> 611 else >> 612 { >> 613 if (std::fabs(yt)<=fDy) >> 614 { >> 615 tmin=0; >> 616 tmax=kInfinity; >> 617 } >> 618 else >> 619 { >> 620 return snxt=kInfinity; >> 621 } 580 } 622 } 581 623 582 // X intersections << 624 // Re-Calc valid intersection range 583 // 625 // 584 G4double tmin2 = tmin1, tmax2 = tmax1; << 626 if (tmin>smin) smin=tmin; 585 G4double cos2 = fPlanes[2].a*v.x() + fPlanes << 627 if (tmax<smax) smax=tmax; 586 G4double disx = fPlanes[2].a*p.x() + fPlanes << 628 if (smax<=smin) 587 G4double dis2 = fPlanes[2].d + disx; << 588 if (dis2 >= -halfCarTolerance) << 589 { 629 { 590 if (cos2 >= 0) return kInfinity; << 630 return snxt=kInfinity; 591 G4double tmp = -dis2/cos2; << 592 if (tmin2 < tmp) tmin2 = tmp; << 593 } 631 } 594 else if (cos2 > 0) << 632 else 595 { 633 { 596 G4double tmp = -dis2/cos2; << 634 // 597 if (tmax2 > tmp) tmax2 = tmp; << 635 // X G4Parallel planes intersection >> 636 // >> 637 xt=p.x()-fTthetaCphi*p.z()-fTalpha*yt; >> 638 vx=v.x()-fTthetaCphi*v.z()-fTalpha*vy; >> 639 if (vx>0) >> 640 { >> 641 max=fDx-xt; >> 642 if (max>kCarTolerance*0.5) >> 643 { >> 644 tmax=max/vx; >> 645 tmin=(-fDx-xt)/vx; >> 646 } >> 647 else >> 648 { >> 649 return snxt=kInfinity; >> 650 } >> 651 } >> 652 else if (vx<0) >> 653 { >> 654 max=-fDx-xt; >> 655 if (max<-kCarTolerance*0.5) >> 656 { >> 657 tmax=max/vx; >> 658 tmin=(fDx-xt)/vx; >> 659 } >> 660 else >> 661 { >> 662 return snxt=kInfinity; >> 663 } >> 664 } >> 665 else >> 666 { >> 667 if (std::fabs(xt)<=fDx) >> 668 { >> 669 tmin=0; >> 670 tmax=kInfinity; >> 671 } >> 672 else >> 673 { >> 674 return snxt=kInfinity; >> 675 } >> 676 } >> 677 if (tmin>smin) smin=tmin; >> 678 if (tmax<smax) smax=tmax; 598 } 679 } 599 680 600 G4double tmin3 = tmin2, tmax3 = tmax2; << 681 if (smax>0&&smin<smax) 601 G4double cos3 = -cos2; << 602 G4double dis3 = fPlanes[3].d - disx; << 603 if (dis3 >= -halfCarTolerance) << 604 { 682 { 605 if (cos3 >= 0) return kInfinity; << 683 if (smin>0) 606 G4double tmp = -dis3/cos3; << 684 { 607 if (tmin3 < tmp) tmin3 = tmp; << 685 snxt=smin; >> 686 } >> 687 else >> 688 { >> 689 snxt=0; >> 690 } 608 } 691 } 609 else if (cos3 > 0) << 692 else 610 { 693 { 611 G4double tmp = -dis3/cos3; << 694 snxt=kInfinity; 612 if (tmax3 > tmp) tmax3 = tmp; << 613 } 695 } 614 << 696 return snxt; 615 // Find distance << 616 // << 617 G4double tmin = tmin3, tmax = tmax3; << 618 if (tmax <= tmin + halfCarTolerance) return << 619 return (tmin < halfCarTolerance ) ? 0. : tmi << 620 } 697 } 621 698 622 ////////////////////////////////////////////// << 699 //////////////////////////////////////////////////////////////////////////// 623 // 700 // 624 // Calculate exact shortest distance to any bo 701 // Calculate exact shortest distance to any boundary from outside 625 // - returns 0 is point inside << 702 // - Returns 0 is point inside 626 703 627 G4double G4Para::DistanceToIn( const G4ThreeVe 704 G4double G4Para::DistanceToIn( const G4ThreeVector& p ) const 628 { 705 { 629 G4double xx = fPlanes[2].a*p.x()+fPlanes[2]. << 706 G4double safe=0.0; 630 G4double dx = std::abs(xx) + fPlanes[2].d; << 707 G4double distz1,distz2,disty1,disty2,distx1,distx2; >> 708 G4double trany,cosy,tranx,cosx; 631 709 632 G4double yy = fPlanes[0].b*p.y()+fPlanes[0]. << 710 // Z planes 633 G4double dy = std::abs(yy) + fPlanes[0].d; << 711 // 634 G4double dxy = std::max(dx,dy); << 712 distz1=p.z()-fDz; >> 713 distz2=-fDz-p.z(); >> 714 if (distz1>distz2) >> 715 { >> 716 safe=distz1; >> 717 } >> 718 else >> 719 { >> 720 safe=distz2; >> 721 } 635 722 636 G4double dz = std::abs(p.z())-fDz; << 723 trany=p.y()-fTthetaSphi*p.z(); // Transformed y into `box' system 637 G4double dist = std::max(dxy,dz); << 638 724 639 return (dist > 0) ? dist : 0.; << 725 // Transformed x into `box' system >> 726 // >> 727 cosy=1.0/std::sqrt(1.0+fTthetaSphi*fTthetaSphi); >> 728 disty1=(trany-fDy)*cosy; >> 729 disty2=(-fDy-trany)*cosy; >> 730 >> 731 if (disty1>safe) safe=disty1; >> 732 if (disty2>safe) safe=disty2; >> 733 >> 734 tranx=p.x()-fTthetaCphi*p.z()-fTalpha*trany; >> 735 cosx=1.0/std::sqrt(1.0+fTalpha*fTalpha+fTthetaCphi*fTthetaCphi); >> 736 distx1=(tranx-fDx)*cosx; >> 737 distx2=(-fDx-tranx)*cosx; >> 738 >> 739 if (distx1>safe) safe=distx1; >> 740 if (distx2>safe) safe=distx2; >> 741 >> 742 if (safe<0) safe=0; >> 743 return safe; 640 } 744 } 641 745 642 ////////////////////////////////////////////// 746 ////////////////////////////////////////////////////////////////////////// 643 // 747 // 644 // Calculate distance to surface of shape from << 748 // Calculate distance to surface of shape from inside 645 // find normal at exit point << 749 // Calculate distance to x/y/z planes - smallest is exiting distance 646 // - when leaving the surface, return 0 << 647 750 648 G4double G4Para::DistanceToOut(const G4ThreeVe 751 G4double G4Para::DistanceToOut(const G4ThreeVector& p, const G4ThreeVector& v, 649 const G4bool ca 752 const G4bool calcNorm, 650 G4bool* v << 753 G4bool *validNorm, G4ThreeVector *n) const 651 { 754 { 652 // Z intersections << 755 ESide side = kUndef; >> 756 G4double snxt; // snxt = return value >> 757 G4double max,tmax; >> 758 G4double yt,vy,xt,vx; >> 759 >> 760 G4double ycomp,calpha,salpha,tntheta,cosntheta; >> 761 >> 762 // >> 763 // Z Intersections 653 // 764 // 654 if ((std::abs(p.z()) - fDz) >= -halfCarToler << 765 >> 766 if (v.z()>0) 655 { 767 { 656 if (calcNorm) << 768 max=fDz-p.z(); >> 769 if (max>kCarTolerance*0.5) 657 { 770 { 658 *validNorm = true; << 771 snxt=max/v.z(); 659 n->set(0, 0, (p.z() < 0) ? -1 : 1); << 772 side=kPZ; >> 773 } >> 774 else >> 775 { >> 776 if (calcNorm) >> 777 { >> 778 *validNorm=true; >> 779 *n=G4ThreeVector(0,0,1); >> 780 } >> 781 return snxt=0; 660 } 782 } 661 return 0.; << 662 } 783 } 663 G4double vz = v.z(); << 784 else if (v.z()<0) 664 G4double tmax = (vz == 0) ? DBL_MAX : (std:: << 665 G4int iside = (vz < 0) ? -4 : -2; // little << 666 << 667 // Y intersections << 668 // << 669 G4double cos0 = fPlanes[0].b*v.y() + fPlanes << 670 if (cos0 > 0) << 671 { 785 { 672 G4double dis0 = fPlanes[0].b*p.y() + fPlan << 786 max=-fDz-p.z(); 673 if (dis0 >= -halfCarTolerance) << 787 if (max<-kCarTolerance*0.5) >> 788 { >> 789 snxt=max/v.z(); >> 790 side=kMZ; >> 791 } >> 792 else 674 { 793 { 675 if (calcNorm) 794 if (calcNorm) 676 { 795 { 677 *validNorm = true; << 796 *validNorm=true; 678 n->set(0, fPlanes[0].b, fPlanes[0].c); << 797 *n=G4ThreeVector(0,0,-1); 679 } 798 } 680 return 0.; << 799 return snxt=0; 681 } 800 } 682 G4double tmp = -dis0/cos0; << 683 if (tmax > tmp) { tmax = tmp; iside = 0; } << 684 } 801 } >> 802 else >> 803 { >> 804 snxt=kInfinity; >> 805 } >> 806 >> 807 // >> 808 // Y plane intersection >> 809 // 685 810 686 G4double cos1 = -cos0; << 811 yt=p.y()-fTthetaSphi*p.z(); 687 if (cos1 > 0) << 812 vy=v.y()-fTthetaSphi*v.z(); >> 813 >> 814 if (vy>0) 688 { 815 { 689 G4double dis1 = fPlanes[1].b*p.y() + fPlan << 816 max=fDy-yt; 690 if (dis1 >= -halfCarTolerance) << 817 if (max>kCarTolerance*0.5) >> 818 { >> 819 tmax=max/vy; >> 820 if (tmax<snxt) >> 821 { >> 822 snxt=tmax; >> 823 side=kPY; >> 824 } >> 825 } >> 826 else 691 { 827 { 692 if (calcNorm) 828 if (calcNorm) >> 829 { >> 830 *validNorm=true; // Leaving via plus Y >> 831 ycomp=1/std::sqrt(1+fTthetaSphi*fTthetaSphi); >> 832 *n=G4ThreeVector(0,ycomp,-fTthetaSphi*ycomp); >> 833 } >> 834 return snxt=0; >> 835 } >> 836 } >> 837 else if (vy<0) >> 838 { >> 839 max=-fDy-yt; >> 840 if (max<-kCarTolerance*0.5) >> 841 { >> 842 tmax=max/vy; >> 843 if (tmax<snxt) 693 { 844 { 694 *validNorm = true; << 845 snxt=tmax; 695 n->set(0, fPlanes[1].b, fPlanes[1].c); << 846 side=kMY; 696 } 847 } 697 return 0.; << 698 } 848 } 699 G4double tmp = -dis1/cos1; << 849 else 700 if (tmax > tmp) { tmax = tmp; iside = 1; } << 850 { >> 851 if (calcNorm) >> 852 { >> 853 *validNorm=true; // Leaving via minus Y >> 854 ycomp=-1/std::sqrt(1+fTthetaSphi*fTthetaSphi); >> 855 *n=G4ThreeVector(0,ycomp,-fTthetaSphi*ycomp); >> 856 } >> 857 return snxt=0; >> 858 } 701 } 859 } 702 860 703 // X intersections << 704 // 861 // 705 G4double cos2 = fPlanes[2].a*v.x() + fPlanes << 862 // X plane intersection 706 if (cos2 > 0) << 863 // >> 864 >> 865 xt=p.x()-fTthetaCphi*p.z()-fTalpha*yt; >> 866 vx=v.x()-fTthetaCphi*v.z()-fTalpha*vy; >> 867 if (vx>0) 707 { 868 { 708 G4double dis2 = fPlanes[2].a*p.x()+fPlanes << 869 max=fDx-xt; 709 if (dis2 >= -halfCarTolerance) << 870 if (max>kCarTolerance*0.5) >> 871 { >> 872 tmax=max/vx; >> 873 if (tmax<snxt) >> 874 { >> 875 snxt=tmax; >> 876 side=kPX; >> 877 } >> 878 } >> 879 else 710 { 880 { 711 if (calcNorm) 881 if (calcNorm) 712 { 882 { 713 *validNorm = true; << 883 *validNorm=true; // Leaving via plus X 714 n->set(fPlanes[2].a, fPlanes[2].b, fP << 884 calpha=1/std::sqrt(1+fTalpha*fTalpha); >> 885 if (fTalpha) >> 886 { >> 887 salpha=-calpha/fTalpha; // NOTE: actually use MINUS std::sin(alpha) >> 888 } >> 889 else >> 890 { >> 891 salpha=0; >> 892 } >> 893 tntheta=fTthetaCphi*calpha+fTthetaSphi*salpha; >> 894 cosntheta=1/std::sqrt(1+tntheta*tntheta); >> 895 *n=G4ThreeVector(calpha*cosntheta,salpha*cosntheta,-tntheta*cosntheta); 715 } 896 } 716 return 0.; << 897 return snxt=0; 717 } 898 } 718 G4double tmp = -dis2/cos2; << 719 if (tmax > tmp) { tmax = tmp; iside = 2; } << 720 } 899 } 721 << 900 else if (vx<0) 722 G4double cos3 = -cos2; << 723 if (cos3 > 0) << 724 { 901 { 725 G4double dis3 = fPlanes[3].a*p.x()+fPlanes << 902 max=-fDx-xt; 726 if (dis3 >= -halfCarTolerance) << 903 if (max<-kCarTolerance*0.5) >> 904 { >> 905 tmax=max/vx; >> 906 if (tmax<snxt) >> 907 { >> 908 snxt=tmax; >> 909 side=kMX; >> 910 } >> 911 } >> 912 else 727 { 913 { 728 if (calcNorm) 914 if (calcNorm) 729 { 915 { 730 *validNorm = true; << 916 *validNorm=true; // Leaving via minus X 731 n->set(fPlanes[3].a, fPlanes[3].b, fP << 917 calpha=1/std::sqrt(1+fTalpha*fTalpha); >> 918 if (fTalpha) >> 919 { >> 920 salpha=-calpha/fTalpha; // NOTE: actually use MINUS std::sin(alpha) >> 921 } >> 922 else >> 923 { >> 924 salpha=0; >> 925 } >> 926 tntheta=fTthetaCphi*calpha+fTthetaSphi*salpha; >> 927 cosntheta=-1/std::sqrt(1+tntheta*tntheta); >> 928 *n=G4ThreeVector(calpha*cosntheta,salpha*cosntheta,-tntheta*cosntheta); >> 929 return snxt=0; 732 } 930 } 733 return 0.; << 734 } 931 } 735 G4double tmp = -dis3/cos3; << 736 if (tmax > tmp) { tmax = tmp; iside = 3; } << 737 } 932 } 738 933 739 // Set normal, if required, and return dista << 934 if (calcNorm) 740 // << 741 if (calcNorm) << 742 { 935 { 743 *validNorm = true; << 936 *validNorm=true; 744 if (iside < 0) << 937 switch (side) 745 n->set(0, 0, iside + 3); // (-4+3)=-1, ( << 938 { 746 else << 939 case kMZ: 747 n->set(fPlanes[iside].a, fPlanes[iside]. << 940 *n=G4ThreeVector(0,0,-1); >> 941 break; >> 942 case kPZ: >> 943 *n=G4ThreeVector(0,0,1); >> 944 break; >> 945 case kMY: >> 946 ycomp=-1/std::sqrt(1+fTthetaSphi*fTthetaSphi); >> 947 *n=G4ThreeVector(0,ycomp,-fTthetaSphi*ycomp); >> 948 break; >> 949 case kPY: >> 950 ycomp=1/std::sqrt(1+fTthetaSphi*fTthetaSphi); >> 951 *n=G4ThreeVector(0,ycomp,-fTthetaSphi*ycomp); >> 952 break; >> 953 case kMX: >> 954 calpha=1/std::sqrt(1+fTalpha*fTalpha); >> 955 if (fTalpha) >> 956 { >> 957 salpha=-calpha/fTalpha; // NOTE: actually use MINUS std::sin(alpha) >> 958 } >> 959 else >> 960 { >> 961 salpha=0; >> 962 } >> 963 tntheta=fTthetaCphi*calpha+fTthetaSphi*salpha; >> 964 cosntheta=-1/std::sqrt(1+tntheta*tntheta); >> 965 *n=G4ThreeVector(calpha*cosntheta,salpha*cosntheta,-tntheta*cosntheta); >> 966 break; >> 967 case kPX: >> 968 calpha=1/std::sqrt(1+fTalpha*fTalpha); >> 969 if (fTalpha) >> 970 { >> 971 salpha=-calpha/fTalpha; // NOTE: actually use MINUS std::sin(alpha) >> 972 } >> 973 else >> 974 { >> 975 salpha=0; >> 976 } >> 977 tntheta=fTthetaCphi*calpha+fTthetaSphi*salpha; >> 978 cosntheta=1/std::sqrt(1+tntheta*tntheta); >> 979 *n=G4ThreeVector(calpha*cosntheta,salpha*cosntheta,-tntheta*cosntheta); >> 980 break; >> 981 default: >> 982 DumpInfo(); >> 983 G4Exception("G4Para::DistanceToOut(p,v,..)","Notification",JustWarning, >> 984 "Undefined side for valid surface normal to solid."); >> 985 break; >> 986 } 748 } 987 } 749 return tmax; << 988 return snxt; 750 } 989 } 751 990 752 ////////////////////////////////////////////// << 991 ///////////////////////////////////////////////////////////////////////////// 753 // 992 // 754 // Calculate exact shortest distance to any bo 993 // Calculate exact shortest distance to any boundary from inside 755 // - returns 0 is point outside << 994 // - Returns 0 is point outside 756 995 757 G4double G4Para::DistanceToOut( const G4ThreeV 996 G4double G4Para::DistanceToOut( const G4ThreeVector& p ) const 758 { 997 { >> 998 G4double safe=0.0; >> 999 G4double distz1,distz2,disty1,disty2,distx1,distx2; >> 1000 G4double trany,cosy,tranx,cosx; >> 1001 759 #ifdef G4CSGDEBUG 1002 #ifdef G4CSGDEBUG 760 if( Inside(p) == kOutside ) 1003 if( Inside(p) == kOutside ) 761 { 1004 { 762 std::ostringstream message; << 1005 G4cout.precision(16) ; 763 G4int oldprc = message.precision(16); << 1006 G4cout << G4endl ; 764 message << "Point p is outside (!?) of sol << 1007 DumpInfo(); 765 message << "Position:\n"; << 1008 G4cout << "Position:" << G4endl << G4endl ; 766 message << " p.x() = " << p.x()/mm << " << 1009 G4cout << "p.x() = " << p.x()/mm << " mm" << G4endl ; 767 message << " p.y() = " << p.y()/mm << " << 1010 G4cout << "p.y() = " << p.y()/mm << " mm" << G4endl ; 768 message << " p.z() = " << p.z()/mm << " << 1011 G4cout << "p.z() = " << p.z()/mm << " mm" << G4endl << G4endl ; 769 G4cout.precision(oldprc) ; << 1012 G4Exception("G4Para::DistanceToOut(p)", "Notification", 770 G4Exception("G4Para::DistanceToOut(p)", "G << 1013 JustWarning, "Point p is outside !?" ); 771 JustWarning, message ); << 1014 } 772 DumpInfo(); << 773 } << 774 #endif 1015 #endif 775 G4double xx = fPlanes[2].a*p.x()+fPlanes[2]. << 776 G4double dx = std::abs(xx) + fPlanes[2].d; << 777 << 778 G4double yy = fPlanes[0].b*p.y()+fPlanes[0]. << 779 G4double dy = std::abs(yy) + fPlanes[0].d; << 780 G4double dxy = std::max(dx,dy); << 781 1016 782 G4double dz = std::abs(p.z())-fDz; << 1017 // Z planes 783 G4double dist = std::max(dxy,dz); << 1018 // >> 1019 distz1=fDz-p.z(); >> 1020 distz2=fDz+p.z(); >> 1021 if (distz1<distz2) >> 1022 { >> 1023 safe=distz1; >> 1024 } >> 1025 else >> 1026 { >> 1027 safe=distz2; >> 1028 } 784 1029 785 return (dist < 0) ? -dist : 0.; << 1030 trany=p.y()-fTthetaSphi*p.z(); // Transformed y into `box' system 786 } << 787 1031 788 ////////////////////////////////////////////// << 1032 // Transformed x into `box' system 789 // << 1033 // 790 // GetEntityType << 1034 cosy=1.0/std::sqrt(1.0+fTthetaSphi*fTthetaSphi); >> 1035 disty1=(fDy-trany)*cosy; >> 1036 disty2=(fDy+trany)*cosy; >> 1037 >> 1038 if (disty1<safe) safe=disty1; >> 1039 if (disty2<safe) safe=disty2; 791 1040 792 G4GeometryType G4Para::GetEntityType() const << 1041 tranx=p.x()-fTthetaCphi*p.z()-fTalpha*trany; 793 { << 1042 cosx=1.0/std::sqrt(1.0+fTalpha*fTalpha+fTthetaCphi*fTthetaCphi); 794 return {"G4Para"}; << 1043 distx1=(fDx-tranx)*cosx; >> 1044 distx2=(fDx+tranx)*cosx; >> 1045 >> 1046 if (distx1<safe) safe=distx1; >> 1047 if (distx2<safe) safe=distx2; >> 1048 >> 1049 if (safe<0) safe=0; >> 1050 return safe; 795 } 1051 } 796 1052 797 ////////////////////////////////////////////// << 1053 //////////////////////////////////////////////////////////////////////////////// 798 // 1054 // 799 // IsFaceted << 1055 // Create a List containing the transformed vertices 800 << 1056 // Ordering [0-3] -fDz cross section 801 G4bool G4Para::IsFaceted() const << 1057 // [4-7] +fDz cross section such that [0] is below [4], 802 { << 1058 // [1] below [5] etc. 803 return true; << 1059 // Note: >> 1060 // Caller has deletion resposibility >> 1061 >> 1062 G4ThreeVectorList* >> 1063 G4Para::CreateRotatedVertices( const G4AffineTransform& pTransform ) const >> 1064 { >> 1065 G4ThreeVectorList *vertices; >> 1066 vertices=new G4ThreeVectorList(); >> 1067 vertices->reserve(8); >> 1068 if (vertices) >> 1069 { >> 1070 G4ThreeVector vertex0(-fDz*fTthetaCphi-fDy*fTalpha-fDx, >> 1071 -fDz*fTthetaSphi-fDy, -fDz); >> 1072 G4ThreeVector vertex1(-fDz*fTthetaCphi-fDy*fTalpha+fDx, >> 1073 -fDz*fTthetaSphi-fDy, -fDz); >> 1074 G4ThreeVector vertex2(-fDz*fTthetaCphi+fDy*fTalpha-fDx, >> 1075 -fDz*fTthetaSphi+fDy, -fDz); >> 1076 G4ThreeVector vertex3(-fDz*fTthetaCphi+fDy*fTalpha+fDx, >> 1077 -fDz*fTthetaSphi+fDy, -fDz); >> 1078 G4ThreeVector vertex4(+fDz*fTthetaCphi-fDy*fTalpha-fDx, >> 1079 +fDz*fTthetaSphi-fDy, +fDz); >> 1080 G4ThreeVector vertex5(+fDz*fTthetaCphi-fDy*fTalpha+fDx, >> 1081 +fDz*fTthetaSphi-fDy, +fDz); >> 1082 G4ThreeVector vertex6(+fDz*fTthetaCphi+fDy*fTalpha-fDx, >> 1083 +fDz*fTthetaSphi+fDy, +fDz); >> 1084 G4ThreeVector vertex7(+fDz*fTthetaCphi+fDy*fTalpha+fDx, >> 1085 +fDz*fTthetaSphi+fDy, +fDz); >> 1086 >> 1087 vertices->push_back(pTransform.TransformPoint(vertex0)); >> 1088 vertices->push_back(pTransform.TransformPoint(vertex1)); >> 1089 vertices->push_back(pTransform.TransformPoint(vertex2)); >> 1090 vertices->push_back(pTransform.TransformPoint(vertex3)); >> 1091 vertices->push_back(pTransform.TransformPoint(vertex4)); >> 1092 vertices->push_back(pTransform.TransformPoint(vertex5)); >> 1093 vertices->push_back(pTransform.TransformPoint(vertex6)); >> 1094 vertices->push_back(pTransform.TransformPoint(vertex7)); >> 1095 } >> 1096 else >> 1097 { >> 1098 DumpInfo(); >> 1099 G4Exception("G4Para::CreateRotatedVertices()", >> 1100 "FatalError", FatalException, >> 1101 "Error in allocation of vertices. Out of memory !"); >> 1102 } >> 1103 return vertices; 804 } 1104 } 805 1105 806 ////////////////////////////////////////////// 1106 ////////////////////////////////////////////////////////////////////////// 807 // 1107 // 808 // Make a clone of the object << 1108 // GetEntityType 809 // << 1109 810 G4VSolid* G4Para::Clone() const << 1110 G4GeometryType G4Para::GetEntityType() const 811 { 1111 { 812 return new G4Para(*this); << 1112 return G4String("G4Para"); 813 } 1113 } 814 1114 815 ////////////////////////////////////////////// 1115 ////////////////////////////////////////////////////////////////////////// 816 // 1116 // 817 // Stream object contents to an output stream 1117 // Stream object contents to an output stream 818 1118 819 std::ostream& G4Para::StreamInfo( std::ostream 1119 std::ostream& G4Para::StreamInfo( std::ostream& os ) const 820 { 1120 { 821 G4double alpha = std::atan(fTalpha); << 822 G4double theta = std::atan(std::sqrt(fTtheta << 823 fTtheta << 824 G4double phi = std::atan2(fTthetaSphi,fTth << 825 << 826 G4long oldprc = os.precision(16); << 827 os << "------------------------------------- 1121 os << "-----------------------------------------------------------\n" 828 << " *** Dump for solid - " << GetName 1122 << " *** Dump for solid - " << GetName() << " ***\n" 829 << " ================================= 1123 << " ===================================================\n" 830 << " Solid type: G4Para\n" 1124 << " Solid type: G4Para\n" 831 << " Parameters:\n" << 1125 << " Parameters: \n" 832 << " half length X: " << fDx/mm << " m << 1126 << " half length X: " << fDx/mm << " mm \n" 833 << " half length Y: " << fDy/mm << " m << 1127 << " half length Y: " << fDy/mm << " mm \n" 834 << " half length Z: " << fDz/mm << " m << 1128 << " half length Z: " << fDz/mm << " mm \n" 835 << " alpha: " << alpha/degree << "degr << 1129 << " std::tan(alpha) : " << fTalpha/degree << " degrees \n" 836 << " theta: " << theta/degree << "degr << 1130 << " std::tan(theta)*std::cos(phi): " << fTthetaCphi/degree << " degrees \n" 837 << " phi: " << phi/degree << "degrees\ << 1131 << " std::tan(theta)*std::sin(phi): " << fTthetaSphi/degree << " degrees \n" 838 << "------------------------------------- 1132 << "-----------------------------------------------------------\n"; 839 os.precision(oldprc); << 840 1133 841 return os; 1134 return os; 842 } 1135 } 843 1136 844 ////////////////////////////////////////////// << 1137 //////////////////////////////////////////////////////////////////////////// 845 // << 846 // Return a point randomly and uniformly selec << 847 << 848 G4ThreeVector G4Para::GetPointOnSurface() cons << 849 { << 850 G4double DyTalpha = fDy*fTalpha; << 851 G4double DzTthetaSphi = fDz*fTthetaSphi; << 852 G4double DzTthetaCphi = fDz*fTthetaCphi; << 853 << 854 // Set vertices << 855 // << 856 G4ThreeVector pt[8]; << 857 pt[0].set(-DzTthetaCphi-DyTalpha-fDx, -DzTth << 858 pt[1].set(-DzTthetaCphi-DyTalpha+fDx, -DzTth << 859 pt[2].set(-DzTthetaCphi+DyTalpha-fDx, -DzTth << 860 pt[3].set(-DzTthetaCphi+DyTalpha+fDx, -DzTth << 861 pt[4].set( DzTthetaCphi-DyTalpha-fDx, DzTth << 862 pt[5].set( DzTthetaCphi-DyTalpha+fDx, DzTth << 863 pt[6].set( DzTthetaCphi+DyTalpha-fDx, DzTth << 864 pt[7].set( DzTthetaCphi+DyTalpha+fDx, DzTth << 865 << 866 // Set areas (-Z, -Y, +Y, -X, +X, +Z) << 867 // << 868 G4ThreeVector vx(fDx, 0, 0); << 869 G4ThreeVector vy(DyTalpha, fDy, 0); << 870 G4ThreeVector vz(DzTthetaCphi, DzTthetaSphi, << 871 << 872 G4double sxy = fDx*fDy; // (vx.cross(vy)).ma << 873 G4double sxz = (vx.cross(vz)).mag(); << 874 G4double syz = (vy.cross(vz)).mag(); << 875 << 876 G4double sface[6] = { sxy, syz, syz, sxz, sx << 877 for (G4int i=1; i<6; ++i) { sface[i] += sfac << 878 << 879 // Select face << 880 // << 881 G4double select = sface[5]*G4UniformRand(); << 882 G4int k = 5; << 883 if (select <= sface[4]) k = 4; << 884 if (select <= sface[3]) k = 3; << 885 if (select <= sface[2]) k = 2; << 886 if (select <= sface[1]) k = 1; << 887 if (select <= sface[0]) k = 0; << 888 << 889 // Generate point << 890 // << 891 G4int ip[6][3] = {{0,1,2}, {0,4,1}, {2,3,6}, << 892 G4double u = G4UniformRand(); << 893 G4double v = G4UniformRand(); << 894 return (1.-u-v)*pt[ip[k][0]] + u*pt[ip[k][1] << 895 } << 896 << 897 ////////////////////////////////////////////// << 898 // 1138 // 899 // Methods for visualisation 1139 // Methods for visualisation 900 1140 901 void G4Para::DescribeYourselfTo ( G4VGraphicsS 1141 void G4Para::DescribeYourselfTo ( G4VGraphicsScene& scene ) const 902 { 1142 { 903 scene.AddSolid (*this); << 1143 scene.AddThis (*this); 904 } 1144 } 905 1145 906 G4Polyhedron* G4Para::CreatePolyhedron () cons 1146 G4Polyhedron* G4Para::CreatePolyhedron () const 907 { 1147 { 908 G4double phi = std::atan2(fTthetaSphi, fTthe 1148 G4double phi = std::atan2(fTthetaSphi, fTthetaCphi); 909 G4double alpha = std::atan(fTalpha); 1149 G4double alpha = std::atan(fTalpha); 910 G4double theta = std::atan(std::sqrt(fTtheta << 1150 G4double theta = std::atan(std::sqrt(fTthetaCphi*fTthetaCphi 911 fTtheta << 1151 +fTthetaSphi*fTthetaSphi)); 912 1152 913 return new G4PolyhedronPara(fDx, fDy, fDz, a 1153 return new G4PolyhedronPara(fDx, fDy, fDz, alpha, theta, phi); 914 } 1154 } 915 #endif << 1155 >> 1156 G4NURBS* G4Para::CreateNURBS () const >> 1157 { >> 1158 // return new G4NURBSbox (fDx, fDy, fDz); >> 1159 return 0 ; >> 1160 } >> 1161 >> 1162 // >> 1163 // >> 1164 /////////////////////////// End of G4Para.cc /////////////////////////// 916 1165