// // ******************************************************************** // * License and Disclaimer * // * * // * The Geant4 software is copyright of the Copyright Holders of * // * the Geant4 Collaboration. It is provided under the terms and * // * conditions of the Geant4 Software License, included in the file * // * LICENSE and available at http://cern.ch/geant4/license . These * // * include a list of copyright holders. * // * * // * Neither the authors of this software system, nor their employing * // * institutes,nor the agencies providing financial support for this * // * work make any representation or warranty, express or implied, * // * regarding this software system or assume any liability for its * // * use. Please see the license in the file LICENSE and URL above * // * for the full disclaimer and the limitation of liability. * // * * // * This code implementation is the result of the scientific and * // * technical work of the GEANT4 collaboration. * // * By using, copying, modifying or distributing the software (or * // * any work based on the software) you agree to acknowledge its * // * use in resulting scientific publications, and indicate your * // * acceptance of all terms of the Geant4 Software license. * // ******************************************************************** // // // $Id: G4TwistTrapAlphaSide.cc,v 1.8 2007/05/23 13:26:06 gcosmo Exp $ // GEANT4 tag $Name: geant4-09-02-ref-02 $ // // // -------------------------------------------------------------------- // GEANT 4 class source file // // // G4TwistTrapAlphaSide.cc // // Author: // // 18/03/2005 - O.Link (Oliver.Link@cern.ch) // // -------------------------------------------------------------------- #include #include "G4TwistTrapAlphaSide.hh" #include "G4JTPolynomialSolver.hh" //===================================================================== //* constructors ------------------------------------------------------ G4TwistTrapAlphaSide:: G4TwistTrapAlphaSide(const G4String &name, G4double PhiTwist, // twist angle G4double pDz, // half z lenght G4double pTheta, // direction between end planes G4double pPhi, // by polar and azimutal angles G4double pDy1, // half y length at -pDz G4double pDx1, // half x length at -pDz,-pDy G4double pDx2, // half x length at -pDz,+pDy G4double pDy2, // half y length at +pDz G4double pDx3, // half x length at +pDz,-pDy G4double pDx4, // half x length at +pDz,+pDy G4double pAlph, // tilt angle at +pDz G4double AngleSide // parity ) : G4VTwistSurface(name) { fAxis[0] = kYAxis; // in local coordinate system fAxis[1] = kZAxis; fAxisMin[0] = -kInfinity ; // Y Axis boundary fAxisMax[0] = kInfinity ; // depends on z !! fAxisMin[1] = -pDz ; // Z Axis boundary fAxisMax[1] = pDz ; fDx1 = pDx1 ; fDx2 = pDx2 ; fDx3 = pDx3 ; fDx4 = pDx4 ; fDy1 = pDy1 ; fDy2 = pDy2 ; fDz = pDz ; fAlph = pAlph ; fTAlph = std::tan(fAlph) ; fTheta = pTheta ; fPhi = pPhi ; // precalculate frequently used parameters fDx4plus2 = fDx4 + fDx2 ; fDx4minus2 = fDx4 - fDx2 ; fDx3plus1 = fDx3 + fDx1 ; fDx3minus1 = fDx3 - fDx1 ; fDy2plus1 = fDy2 + fDy1 ; fDy2minus1 = fDy2 - fDy1 ; fa1md1 = 2*fDx2 - 2*fDx1 ; fa2md2 = 2*fDx4 - 2*fDx3 ; fPhiTwist = PhiTwist ; // dphi fAngleSide = AngleSide ; // 0,90,180,270 deg fdeltaX = 2 * fDz * std::tan(fTheta) * std::cos(fPhi); // dx in surface equation fdeltaY = 2 * fDz * std::tan(fTheta) * std::sin(fPhi); // dy in surface equation fRot.rotateZ( AngleSide ) ; fTrans.set(0, 0, 0); // No Translation fIsValidNorm = false; SetCorners() ; SetBoundaries() ; } //===================================================================== //* Fake default constructor ------------------------------------------ G4TwistTrapAlphaSide::G4TwistTrapAlphaSide( __void__& a ) : G4VTwistSurface(a) { } //===================================================================== //* destructor -------------------------------------------------------- G4TwistTrapAlphaSide::~G4TwistTrapAlphaSide() { } //===================================================================== //* GetNormal --------------------------------------------------------- G4ThreeVector G4TwistTrapAlphaSide::GetNormal(const G4ThreeVector &tmpxx, G4bool isGlobal) { // GetNormal returns a normal vector at a surface (or very close // to surface) point at tmpxx. // If isGlobal=true, it returns the normal in global coordinate. // G4ThreeVector xx; if (isGlobal) { xx = ComputeLocalPoint(tmpxx); if ((xx - fCurrentNormal.p).mag() < 0.5 * kCarTolerance) { return ComputeGlobalDirection(fCurrentNormal.normal); } } else { xx = tmpxx; if (xx == fCurrentNormal.p) { return fCurrentNormal.normal; } } G4double phi ; G4double u ; GetPhiUAtX(xx,phi,u) ; // phi,u for point xx close to surface G4ThreeVector normal = NormAng(phi,u) ; // the normal vector at phi,u #ifdef G4TWISTDEBUG G4cout << "normal vector = " << normal << G4endl ; G4cout << "phi = " << phi << " , u = " << u << G4endl ; #endif if (isGlobal) { fCurrentNormal.normal = ComputeGlobalDirection(normal.unit()); } else { fCurrentNormal.normal = normal.unit(); } return fCurrentNormal.normal; } //===================================================================== //* DistanceToSurface ------------------------------------------------- G4int G4TwistTrapAlphaSide::DistanceToSurface(const G4ThreeVector &gp, const G4ThreeVector &gv, G4ThreeVector gxx[], G4double distance[], G4int areacode[], G4bool isvalid[], EValidate validate) { static const G4double ctol = 0.5 * kCarTolerance; static const G4double pihalf = pi/2 ; G4bool IsParallel = false ; G4bool IsConverged = false ; G4int nxx = 0 ; // number of physical solutions fCurStatWithV.ResetfDone(validate, &gp, &gv); if (fCurStatWithV.IsDone()) { for (register int i=0; i fYAxisMax - ctol) { areacode |= (sAxis0 & (sAxisY | sAxisMax)) | sBoundary; if (yprime >= fYAxisMax + ctol) { isoutside = true; } } // test boundary of z-axis if (xx.z() < fAxisMin[zaxis] + ctol) { areacode |= (sAxis1 & (sAxisZ | sAxisMin)); if (areacode & sBoundary) // xx is on the corner { areacode |= sCorner; } else { areacode |= sBoundary; } if (xx.z() <= fAxisMin[zaxis] - ctol) { isoutside = true; } } else if (xx.z() > fAxisMax[zaxis] - ctol) { areacode |= (sAxis1 & (sAxisZ | sAxisMax)); if (areacode & sBoundary) // xx is on the corner { areacode |= sCorner; } else { areacode |= sBoundary; } if (xx.z() >= fAxisMax[zaxis] + ctol) { isoutside = true; } } // if isoutside = true, clear inside bit. // if not on boundary, add axis information. if (isoutside) { G4int tmpareacode = areacode & (~sInside); areacode = tmpareacode; } else if ((areacode & sBoundary) != sBoundary) { areacode |= (sAxis0 & sAxisY) | (sAxis1 & sAxisZ); } } else { // boundary of y-axis if (yprime < fYAxisMin ) { areacode |= (sAxis0 & (sAxisY | sAxisMin)) | sBoundary; } else if (yprime > fYAxisMax) { areacode |= (sAxis0 & (sAxisY | sAxisMax)) | sBoundary; } // boundary of z-axis if (xx.z() < fAxisMin[zaxis]) { areacode |= (sAxis1 & (sAxisZ | sAxisMin)); if (areacode & sBoundary) // xx is on the corner { areacode |= sCorner; } else { areacode |= sBoundary; } } else if (xx.z() > fAxisMax[zaxis]) { areacode |= (sAxis1 & (sAxisZ | sAxisMax)) ; if (areacode & sBoundary) // xx is on the corner { areacode |= sCorner; } else { areacode |= sBoundary; } } if ((areacode & sBoundary) != sBoundary) { areacode |= (sAxis0 & sAxisY) | (sAxis1 & sAxisZ); } } return areacode; } else { G4Exception("G4TwistTrapAlphaSide::GetAreaCode()", "NotImplemented", FatalException, "Feature NOT implemented !"); } return areacode; } //===================================================================== //* SetCorners() ------------------------------------------------------ void G4TwistTrapAlphaSide::SetCorners() { // Set Corner points in local coodinate. if (fAxis[0] == kYAxis && fAxis[1] == kZAxis) { G4double x, y, z; // corner of Axis0min and Axis1min // x = -fdeltaX/2. + (fDx1 - fDy1*fTAlph)*std::cos(fPhiTwist/2.) - fDy1*std::sin(fPhiTwist/2.); y = -fdeltaY/2. - fDy1*std::cos(fPhiTwist/2.) + (-fDx1 + fDy1*fTAlph)*std::sin(fPhiTwist/2.); z = -fDz ; // G4cout << "SetCorners: " << x << ", " << y << ", " << z << G4endl ; SetCorner(sC0Min1Min, x, y, z); // corner of Axis0max and Axis1min // x = -fdeltaX/2. + (fDx2 + fDy1*fTAlph)*std::cos(fPhiTwist/2.) + fDy1*std::sin(fPhiTwist/2.); y = -fdeltaY/2. + fDy1*std::cos(fPhiTwist/2.) - (fDx2 + fDy1*fTAlph)*std::sin(fPhiTwist/2.); z = -fDz ; // G4cout << "SetCorners: " << x << ", " << y << ", " << z << G4endl ; SetCorner(sC0Max1Min, x, y, z); // corner of Axis0max and Axis1max // x = fdeltaX/2. + (fDx4 + fDy2*fTAlph)*std::cos(fPhiTwist/2.) - fDy2*std::sin(fPhiTwist/2.); y = fdeltaY/2. + fDy2*std::cos(fPhiTwist/2.) + (fDx4 + fDy2*fTAlph)*std::sin(fPhiTwist/2.); z = fDz ; // G4cout << "SetCorners: " << x << ", " << y << ", " << z << G4endl ; SetCorner(sC0Max1Max, x, y, z); // corner of Axis0min and Axis1max x = fdeltaX/2. + (fDx3 - fDy2*fTAlph)*std::cos(fPhiTwist/2.) + fDy2*std::sin(fPhiTwist/2.) ; y = fdeltaY/2. - fDy2*std::cos(fPhiTwist/2.) + (fDx3 - fDy2*fTAlph)*std::sin(fPhiTwist/2.) ; z = fDz ; // G4cout << "SetCorners: " << x << ", " << y << ", " << z << G4endl ; SetCorner(sC0Min1Max, x, y, z); } else { G4Exception("G4TwistTrapAlphaSide::SetCorners()", "NotImplemented", FatalException, "Method NOT implemented !"); } } //===================================================================== //* SetBoundaries() --------------------------------------------------- void G4TwistTrapAlphaSide::SetBoundaries() { // Set direction-unit vector of boundary-lines in local coodinate. // G4ThreeVector direction; if (fAxis[0] == kYAxis && fAxis[1] == kZAxis) { // sAxis0 & sAxisMin direction = GetCorner(sC0Min1Max) - GetCorner(sC0Min1Min); direction = direction.unit(); SetBoundary(sAxis0 & (sAxisY | sAxisMin), direction, GetCorner(sC0Min1Min), sAxisZ) ; // sAxis0 & sAxisMax direction = GetCorner(sC0Max1Max) - GetCorner(sC0Max1Min); direction = direction.unit(); SetBoundary(sAxis0 & (sAxisY | sAxisMax), direction, GetCorner(sC0Max1Min), sAxisZ); // sAxis1 & sAxisMin direction = GetCorner(sC0Max1Min) - GetCorner(sC0Min1Min); direction = direction.unit(); SetBoundary(sAxis1 & (sAxisZ | sAxisMin), direction, GetCorner(sC0Min1Min), sAxisY); // sAxis1 & sAxisMax direction = GetCorner(sC0Max1Max) - GetCorner(sC0Min1Max); direction = direction.unit(); SetBoundary(sAxis1 & (sAxisZ | sAxisMax), direction, GetCorner(sC0Min1Max), sAxisY); } else { G4Exception("G4TwistTrapAlphaSide::SetCorners()", "NotImplemented", FatalException, "Feature NOT implemented !"); } } //===================================================================== //* GetPhiUAtX -------------------------------------------------------- void G4TwistTrapAlphaSide::GetPhiUAtX( G4ThreeVector p, G4double &phi, G4double &u ) { // find closest point XX on surface for a given point p // X0 is a point on the surface, d is the direction // ( both for a fixed z = pz) // phi is given by the z coordinate of p phi = p.z()/(2*fDz)*fPhiTwist ; u = (fPhiTwist*(2*fDx1*fDx1 - 2*fDx2*fDx2 - fa1md1*(fDx3 + fDx4) - 4*(fDx3plus1 + fDx4plus2)*fDy1*fTAlph) - 2*(2*fDx1*fDx1 - 2*fDx2*fDx2 + fa1md1*(fDx3 + fDx4) + 4*(fDx3minus1 + fDx4minus2)*fDy1*fTAlph)*phi - 4*(fa1md1*(fdeltaX*phi - fPhiTwist*p.x()) + 4*fDy1*(fdeltaY*phi + fdeltaX*fTAlph*phi - fPhiTwist*(fTAlph*p.x() + p.y())))*std::cos(phi) - 4*(fa1md1*fdeltaY*phi - 4*fdeltaX*fDy1*phi + 4*fdeltaY*fDy1*fTAlph*phi + 4*fDy1*fPhiTwist*p.x() - fPhiTwist*(fa1md1 + 4*fDy1*fTAlph)*p.y())*std::sin(phi)) /(fDy1* fPhiTwist*((std::fabs(((fa1md1 + 4*fDy1*fTAlph)*std::cos(phi)) /fDy1 - 4*std::sin(phi))) *(std::fabs(((fa1md1 + 4*fDy1*fTAlph)*std::cos(phi)) /fDy1 - 4*std::sin(phi))) + (std::fabs(4*std::cos(phi) + ((fa1md1 + 4*fDy1*fTAlph)*std::sin(phi))/fDy1)) * (std::fabs(4*std::cos(phi) + ((fa1md1 + 4*fDy1*fTAlph)*std::sin(phi))/fDy1)))) ; } //===================================================================== //* ProjectPoint ------------------------------------------------------ G4ThreeVector G4TwistTrapAlphaSide::ProjectPoint(const G4ThreeVector &p, G4bool isglobal) { // Get Rho at p.z() on Hyperbolic Surface. G4ThreeVector tmpp; if (isglobal) { tmpp = fRot.inverse()*p - fTrans; } else { tmpp = p; } G4double phi ; G4double u ; GetPhiUAtX( tmpp, phi, u ) ; // calculate (phi, u) for a point p close the surface G4ThreeVector xx = SurfacePoint(phi,u) ; // transform back to cartesian coordinates if (isglobal) { return (fRot * xx + fTrans); } else { return xx; } } //===================================================================== //* GetFacets --------------------------------------------------------- void G4TwistTrapAlphaSide::GetFacets( G4int m, G4int n, G4double xyz[][3], G4int faces[][4], G4int iside ) { G4double phi ; G4double b ; G4double z, u ; // the two parameters for the surface equation G4ThreeVector p ; // a point on the surface, given by (z,u) G4int nnode ; G4int nface ; // calculate the (n-1)*(m-1) vertices for ( register int i = 0 ; i