// // ******************************************************************** // * 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: G4VTwistSurface.cc,v 1.9 2007/05/31 13:52:48 gcosmo Exp $ // GEANT4 tag $Name: geant4-09-03 $ // // // -------------------------------------------------------------------- // GEANT 4 class source file // // // G4VTwistSurface.cc // // Author: // 01-Aug-2002 - Kotoyo Hoshina (hoshina@hepburn.s.chiba-u.ac.jp) // // History: // 13-Nov-2003 - O.Link (Oliver.Link@cern.ch), Integration in Geant4 // from original version in Jupiter-2.5.02 application. // -------------------------------------------------------------------- #include #include "G4VTwistSurface.hh" #include "G4GeometryTolerance.hh" const G4int G4VTwistSurface::sOutside = 0x00000000; const G4int G4VTwistSurface::sInside = 0x10000000; const G4int G4VTwistSurface::sBoundary = 0x20000000; const G4int G4VTwistSurface::sCorner = 0x40000000; const G4int G4VTwistSurface::sC0Min1Min = 0x40000101; const G4int G4VTwistSurface::sC0Max1Min = 0x40000201; const G4int G4VTwistSurface::sC0Max1Max = 0x40000202; const G4int G4VTwistSurface::sC0Min1Max = 0x40000102; const G4int G4VTwistSurface::sAxisMin = 0x00000101; const G4int G4VTwistSurface::sAxisMax = 0x00000202; const G4int G4VTwistSurface::sAxisX = 0x00000404; const G4int G4VTwistSurface::sAxisY = 0x00000808; const G4int G4VTwistSurface::sAxisZ = 0x00000C0C; const G4int G4VTwistSurface::sAxisRho = 0x00001010; const G4int G4VTwistSurface::sAxisPhi = 0x00001414; // mask const G4int G4VTwistSurface::sAxis0 = 0x0000FF00; const G4int G4VTwistSurface::sAxis1 = 0x000000FF; const G4int G4VTwistSurface::sSizeMask = 0x00000303; const G4int G4VTwistSurface::sAxisMask = 0x0000FCFC; const G4int G4VTwistSurface::sAreaMask = 0XF0000000; //===================================================================== //* constructors ------------------------------------------------------ G4VTwistSurface::G4VTwistSurface(const G4String &name) : fName(name) { fAxis[0] = kUndefined; fAxis[1] = kUndefined; fAxisMin[0] = kInfinity; fAxisMin[1] = kInfinity; fAxisMax[0] = kInfinity; fAxisMax[1] = kInfinity; fHandedness = 1; G4int i; for (i=0; i<4; i++) { fCorners[i].set(kInfinity, kInfinity, kInfinity); fNeighbours[i] = 0; } fCurrentNormal.p.set(kInfinity, kInfinity, kInfinity); fAmIOnLeftSide.me.set(kInfinity, kInfinity, kInfinity); fAmIOnLeftSide.vec.set(kInfinity, kInfinity, kInfinity); kCarTolerance = G4GeometryTolerance::GetInstance()->GetSurfaceTolerance(); } G4VTwistSurface::G4VTwistSurface(const G4String &name, const G4RotationMatrix &rot, const G4ThreeVector &tlate, G4int handedness, const EAxis axis0 , const EAxis axis1 , G4double axis0min, G4double axis1min, G4double axis0max, G4double axis1max ) : fName(name) { fAxis[0] = axis0; fAxis[1] = axis1; fAxisMin[0] = axis0min; fAxisMin[1] = axis1min; fAxisMax[0] = axis0max; fAxisMax[1] = axis1max; fHandedness = handedness; fRot = rot; fTrans = tlate; G4int i; for (i=0; i<4; i++) { fCorners[i].set(kInfinity, kInfinity, kInfinity); fNeighbours[i] = 0; } fCurrentNormal.p.set(kInfinity, kInfinity, kInfinity); fAmIOnLeftSide.me.set(kInfinity, kInfinity, kInfinity); fAmIOnLeftSide.vec.set(kInfinity, kInfinity, kInfinity); kCarTolerance = G4GeometryTolerance::GetInstance()->GetSurfaceTolerance(); } //===================================================================== //* Fake default constructor ------------------------------------------ G4VTwistSurface::G4VTwistSurface( __void__& ) : fName("") { } //===================================================================== //* destructor -------------------------------------------------------- G4VTwistSurface::~G4VTwistSurface() { } //===================================================================== //* AmIOnLeftSide ----------------------------------------------------- G4int G4VTwistSurface::AmIOnLeftSide(const G4ThreeVector &me, const G4ThreeVector &vec, G4bool withtol) { // AmIOnLeftSide returns phi-location of "me" // (phi relation between me and vec projected on z=0 plane). // If "me" is on -ve-phi-side of "vec", it returns 1. // On the other hand, if "me" is on +ve-phi-side of "vec", // it returns -1. // (The return value represents z-coordinate of normal vector // of me.cross(vec).) // If me is on boundary of vec, return 0. static const G4double kAngTolerance = G4GeometryTolerance::GetInstance()->GetAngularTolerance(); static G4RotationMatrix unitrot; // unit matrix static const G4RotationMatrix rottol = unitrot.rotateZ(0.5*kAngTolerance); static const G4RotationMatrix invrottol = unitrot.rotateZ(-1.*kAngTolerance); if (fAmIOnLeftSide.me == me && fAmIOnLeftSide.vec == vec && fAmIOnLeftSide.withTol == withtol) { return fAmIOnLeftSide.amIOnLeftSide; } fAmIOnLeftSide.me = me; fAmIOnLeftSide.vec = vec; fAmIOnLeftSide.withTol = withtol; G4ThreeVector met = (G4ThreeVector(me.x(), me.y(), 0.)).unit(); G4ThreeVector vect = (G4ThreeVector(vec.x(), vec.y(), 0.)).unit(); G4ThreeVector ivect = invrottol * vect; G4ThreeVector rvect = rottol * vect; G4double metcrossvect = met.x() * vect.y() - met.y() * vect.x(); if (withtol) { if (met.x() * ivect.y() - met.y() * ivect.x() > 0 && metcrossvect >= 0) { fAmIOnLeftSide.amIOnLeftSide = 1; } else if (met.x() * rvect.y() - met.y() * rvect.x() < 0 && metcrossvect <= 0) { fAmIOnLeftSide.amIOnLeftSide = -1; } else { fAmIOnLeftSide.amIOnLeftSide = 0; } } else { if (metcrossvect > 0) { fAmIOnLeftSide.amIOnLeftSide = 1; } else if (metcrossvect < 0 ) { fAmIOnLeftSide.amIOnLeftSide = -1; } else { fAmIOnLeftSide.amIOnLeftSide = 0; } } #ifdef G4TWISTDEBUG G4cout << " === G4VTwistSurface::AmIOnLeftSide() ==============" << G4endl; G4cout << " Name , returncode : " << fName << " " << fAmIOnLeftSide.amIOnLeftSide << G4endl; G4cout << " me, vec : " << std::setprecision(14) << me << " " << vec << G4endl; G4cout << " met, vect : " << met << " " << vect << G4endl; G4cout << " ivec, rvec : " << ivect << " " << rvect << G4endl; G4cout << " met x vect : " << metcrossvect << G4endl; G4cout << " met x ivec : " << met.cross(ivect) << G4endl; G4cout << " met x rvec : " << met.cross(rvect) << G4endl; G4cout << " ==============================================" << G4endl; #endif return fAmIOnLeftSide.amIOnLeftSide; } //===================================================================== //* DistanceToBoundary ------------------------------------------------ G4double G4VTwistSurface::DistanceToBoundary(G4int areacode, G4ThreeVector &xx, const G4ThreeVector &p) { // DistanceToBoundary // // return distance to nearest boundary from arbitrary point p // in local coodinate. // Argument areacode must be one of them: // sAxis0 & sAxisMin, sAxis0 & sAxisMax, // sAxis1 & sAxisMin, sAxis1 & sAxisMax. // G4ThreeVector d; // direction vector of the boundary G4ThreeVector x0; // reference point of the boundary G4double dist = kInfinity; G4int boundarytype; if (IsAxis0(areacode) && IsAxis1(areacode)) { G4cerr << "ERROR - G4VTwistSurface::DistanceToBoundary()" << G4endl << " Point is in the corner area. This function returns" << G4endl << " a direction vector of a boundary line." << G4endl << " areacode = " << areacode << G4endl; G4Exception("G4VTwistSurface::DistanceToBoundary()", "InvalidSetup", FatalException, "Point is in the corner area."); } else if (IsAxis0(areacode) || IsAxis1(areacode)) { GetBoundaryParameters(areacode, d, x0, boundarytype); if (boundarytype == sAxisPhi) { G4double t = x0.getRho() / p.getRho(); xx.set(t*p.x(), t*p.y(), x0.z()); dist = (xx - p).mag(); } else { // linear boundary // sAxisX, sAxisY, sAxisZ, sAxisRho dist = DistanceToLine(p, x0, d, xx); } } else { G4cerr << "ERROR - G4VTwistSurface::DistanceToBoundary()" << G4endl << " areacode = " << areacode << G4endl; G4Exception("G4VTwistSurface::DistanceToBoundary()", "InvalidSetup", FatalException, "Bad areacode of boundary."); } return dist; } //===================================================================== //* DistanceToIn ------------------------------------------------------ G4double G4VTwistSurface::DistanceToIn(const G4ThreeVector &gp, const G4ThreeVector &gv, G4ThreeVector &gxxbest) { #ifdef G4TWISTDEBUG G4cout << " ~~~~~ G4VTwistSurface::DistanceToIn(p,v) - Start ~~~~~" << G4endl; G4cout << " Name : " << fName << G4endl; G4cout << " gp : " << gp << G4endl; G4cout << " gv : " << gv << G4endl; G4cout << "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" << G4endl; #endif G4ThreeVector gxx[G4VSURFACENXX]; G4double distance[G4VSURFACENXX] ; G4int areacode[G4VSURFACENXX] ; G4bool isvalid[G4VSURFACENXX] ; for (G4int i = 0 ; i= 0) { #ifdef G4TWISTDEBUG G4cout << " G4VTwistSurface::DistanceToIn(p,v): " << "particle goes outword the surface." << G4endl; #endif continue; } // // accept this intersection if the intersection is inside. // if (IsInside(areacode[i])) { if (distance[i] < bestdistance) { bestdistance = distance[i]; bestgxx = gxx[i]; besti = i; #ifdef G4TWISTDEBUG G4cout << " G4VTwistSurface::DistanceToIn(p,v): " << " areacode sInside name, distance = " << fName << " "<< bestdistance << G4endl; #endif } // // else, the intersection is on boundary or corner. // } else { G4VTwistSurface *neighbours[2]; G4bool isaccepted[2] = {false, false}; G4int nneighbours = GetNeighbours(areacode[i], neighbours); for (G4int j=0; j< nneighbours; j++) { // if on corner, nneighbours = 2. // if on boundary, nneighbours = 1. G4ThreeVector tmpgxx[G4VSURFACENXX]; G4double tmpdist[G4VSURFACENXX] ; G4int tmpareacode[G4VSURFACENXX] ; G4bool tmpisvalid[G4VSURFACENXX] ; for (G4int l = 0 ; lDistanceToSurface( gp, gv, tmpgxx, tmpdist, tmpareacode, tmpisvalid, kValidateWithTol); G4ThreeVector neighbournormal; for (G4int k=0; k< tmpnxx; k++) { // // if tmpxx[k] is valid && sInside, the final winner must // be neighbour surface. return kInfinity. // else , choose tmpxx on same boundary of xx, then check normal // if (IsInside(tmpareacode[k])) { #ifdef G4TWISTDEBUG G4cout << " G4VTwistSurface:DistanceToIn(p,v): " << " intersection "<< tmpgxx[k] << G4endl << " is inside of neighbour surface of " << fName << " . returning kInfinity." << G4endl; G4cout << "~~~~~ G4VTwistSurface::DistanceToIn(p,v) - return ~~~~" << G4endl; G4cout << " No intersections " << G4endl; G4cout << " Name : " << fName << G4endl; G4cout << "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" << G4endl; #endif if (tmpisvalid[k]) return kInfinity; continue; // // if tmpxx[k] is valid && sInside, the final winner must // be neighbour surface. return . // } else if (IsSameBoundary(this,areacode[i], neighbours[j], tmpareacode[k])) { // tmpxx[k] is same boundary (or corner) of xx. neighbournormal = neighbours[j]->GetNormal(tmpgxx[k], true); if (neighbournormal * gv < 0) isaccepted[j] = true; } } // if nneighbours = 1, chabge isaccepted[1] before // exiting neighboursurface loop. if (nneighbours == 1) isaccepted[1] = true; } // neighboursurface loop end // now, we can accept xx intersection if (isaccepted[0] == true && isaccepted[1] == true) { if (distance[i] < bestdistance) { bestdistance = distance[i]; gxxbest = gxx[i]; besti = i; #ifdef G4TWISTDEBUG G4cout << " G4VTwistSurface::DistanceToIn(p,v): " << " areacode sBoundary & sBoundary distance = " << fName << " " << distance[i] << G4endl; #endif } } } // else end } // intersection loop end gxxbest = bestgxx; #ifdef G4TWISTDEBUG if (besti < 0) { G4cout << "~~~~~ G4VTwistSurface::DistanceToIn(p,v) - return ~~~~" << G4endl; G4cout << " No intersections " << G4endl; G4cout << " Name : " << fName << G4endl; G4cout << "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" << G4endl; } else { G4cout << "~~~~~ G4VTwistSurface::DistanceToIn(p,v) : return ~~~~" << G4endl; G4cout << " Name, i : " << fName << " , " << besti << G4endl; G4cout << " gxx[i] : " << gxxbest << G4endl; G4cout << " bestdist : " << bestdistance << G4endl; G4cout << "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" << G4endl; } #endif return bestdistance; } //===================================================================== //* DistanceToOut(p, v) ----------------------------------------------- G4double G4VTwistSurface::DistanceToOut(const G4ThreeVector &gp, const G4ThreeVector &gv, G4ThreeVector &gxxbest) { #ifdef G4TWISTDEBUG G4cout << "~~~~~ G4VTwistSurface::DistanceToOut(p,v) - Start ~~~~" << G4endl; G4cout << " Name : " << fName << G4endl; G4cout << " gp : " << gp << G4endl; G4cout << " gv : " << gv << G4endl; G4cout << "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" << G4endl; #endif G4ThreeVector gxx[G4VSURFACENXX]; G4double distance[G4VSURFACENXX] ; G4int areacode[G4VSURFACENXX] ; G4bool isvalid[G4VSURFACENXX] ; G4int i; for ( i = 0 ; iComputeGlobalPoint(surface1->GetCorner(areacode1)); G4ThreeVector corner2 = surface2->ComputeGlobalPoint(surface2->GetCorner(areacode2)); if ((corner1 - corner2).mag() < kCarTolerance) { return true; } else { return false; } } else if ((IsBoundary(areacode1, testbitmode) && (!iscorner[0])) && (IsBoundary(areacode2, testbitmode) && (!iscorner[1]))) { // on boundary G4ThreeVector d1, d2, ld1, ld2; G4ThreeVector x01, x02, lx01, lx02; G4int type1, type2; surface1->GetBoundaryParameters(areacode1, ld1, lx01, type1); surface2->GetBoundaryParameters(areacode2, ld2, lx02, type2); x01 = surface1->ComputeGlobalPoint(lx01); x02 = surface2->ComputeGlobalPoint(lx02); d1 = surface1->ComputeGlobalDirection(ld1); d2 = surface2->ComputeGlobalDirection(ld2); if ((x01 - x02).mag() < kCarTolerance && (d1 - d2).mag() < kCarTolerance) { return true; } else { return false; } } else { return false; } } //===================================================================== //* GetBoundaryParameters --------------------------------------------- void G4VTwistSurface::GetBoundaryParameters(const G4int &areacode, G4ThreeVector &d, G4ThreeVector &x0, G4int &boundarytype) const { // areacode must be one of them: // sAxis0 & sAxisMin, sAxis0 & sAxisMax, // sAxis1 & sAxisMin, sAxis1 & sAxisMax. G4int i; for (i=0; i<4; i++) { if (fBoundaries[i].GetBoundaryParameters(areacode, d, x0, boundarytype)) { return; } } G4cerr << "ERROR - G4VTwistSurface::GetBoundaryParameters()" << G4endl << " Boundary at areacode " << std::hex << areacode << std::dec << G4endl << " is not be registered." << G4endl; G4Exception("G4VTwistSurface::GetBoundaryParameters()", "InvalidSetup", FatalException, "Not registered boundary."); } //===================================================================== //* GetBoundaryAtPZ --------------------------------------------------- G4ThreeVector G4VTwistSurface::GetBoundaryAtPZ(G4int areacode, const G4ThreeVector &p) const { // areacode must be one of them: // sAxis0 & sAxisMin, sAxis0 & sAxisMax, // sAxis1 & sAxisMin, sAxis1 & sAxisMax. if (areacode & sAxis0 && areacode & sAxis1) { G4cerr << "ERROR - G4VTwistSurface::GetBoundaryAtPZ()" << G4endl << " Point is in the corner area. This function returns" << G4endl << " a direction vector of a boundary line." << G4endl << " areacode = " << areacode << G4endl; G4Exception("G4VTwistSurface::GetBoundaryAtPZ()", "InvalidCondition", FatalException, "Point is in the corner area."); } G4ThreeVector d; G4ThreeVector x0; G4int boundarytype; G4bool found = false; for (G4int i=0; i<4; i++) { if (fBoundaries[i].GetBoundaryParameters(areacode, d, x0, boundarytype)){ found = true; continue; } } if (!found) { G4cerr << "ERROR - G4VTwistSurface::GetBoundaryAtPZ()" << G4endl << " Boundary at areacode " << areacode << G4endl << " is not be registered." << G4endl; G4Exception("G4VTwistSurface::GetBoundaryAtPZ()", "InvalidSetup", FatalException, "Not registered boundary."); } if (((boundarytype & sAxisPhi) == sAxisPhi) || ((boundarytype & sAxisRho) == sAxisRho)) { G4cerr << "ERROR - G4VTwistSurface::GetBoundaryAtPZ()" << G4endl << " Boundary at areacode " << areacode << G4endl << " is not a z-depended line." << G4endl; G4Exception("G4VTwistSurface::GetBoundaryAtPZ()", "InvalidSetup", FatalException, "Not a z-depended line boundary."); } return ((p.z() - x0.z()) / d.z()) * d + x0; } //===================================================================== //* SetCorner --------------------------------------------------------- void G4VTwistSurface::SetCorner(G4int areacode, G4double x, G4double y, G4double z) { if ((areacode & sCorner) != sCorner){ G4cerr << "ERROR - G4VTwistSurface::SetCorner()" << G4endl << " areacode " << areacode << G4endl; G4Exception("G4VTwistSurface::SetCorner()", "InvalidSetup", FatalException, "Area code must represents corner."); } if ((areacode & sC0Min1Min) == sC0Min1Min) { fCorners[0].set(x, y, z); } else if ((areacode & sC0Max1Min) == sC0Max1Min) { fCorners[1].set(x, y, z); } else if ((areacode & sC0Max1Max) == sC0Max1Max) { fCorners[2].set(x, y, z); } else if ((areacode & sC0Min1Max) == sC0Min1Max) { fCorners[3].set(x, y, z); } } //===================================================================== //* SetBoundaryAxis --------------------------------------------------- void G4VTwistSurface::GetBoundaryAxis(G4int areacode, EAxis axis[]) const { if ((areacode & sBoundary) != sBoundary) { G4Exception("G4VTwistSurface::GetBoundaryAxis()", "InvalidCondition", FatalException, "Not located on a boundary!"); } G4int i; for (i=0; i<2; i++) { G4int whichaxis = 0 ; if (i == 0) { whichaxis = sAxis0; } else if (i == 1) { whichaxis = sAxis1; } // extracted axiscode of whichaxis G4int axiscode = whichaxis & sAxisMask & areacode ; if (axiscode) { if (axiscode == (whichaxis & sAxisX)) { axis[i] = kXAxis; } else if (axiscode == (whichaxis & sAxisY)) { axis[i] = kYAxis; } else if (axiscode == (whichaxis & sAxisZ)) { axis[i] = kZAxis; } else if (axiscode == (whichaxis & sAxisRho)) { axis[i] = kRho; } else if (axiscode == (whichaxis & sAxisPhi)) { axis[i] = kPhi; } else { G4cerr << "ERROR - G4VTwistSurface::GetBoundaryAxis()" << G4endl << " areacode " << areacode << G4endl; G4Exception("G4VTwistSurface::GetBoundaryAxis()", "InvalidSetup", FatalException, "Not supported areacode."); } } } } //===================================================================== //* SetBoundaryLimit -------------------------------------------------- void G4VTwistSurface::GetBoundaryLimit(G4int areacode, G4double limit[]) const { if (areacode & sCorner) { if (areacode & sC0Min1Max) { limit[0] = fAxisMin[0]; limit[1] = fAxisMin[1]; } else if (areacode & sC0Max1Min) { limit[0] = fAxisMax[0]; limit[1] = fAxisMin[1]; } else if (areacode & sC0Max1Max) { limit[0] = fAxisMax[0]; limit[1] = fAxisMax[1]; } else if (areacode & sC0Min1Max) { limit[0] = fAxisMin[0]; limit[1] = fAxisMax[1]; } } else if (areacode & sBoundary) { if (areacode & (sAxis0 | sAxisMin)) { limit[0] = fAxisMin[0]; } else if (areacode & (sAxis1 | sAxisMin)) { limit[0] = fAxisMin[1]; } else if (areacode & (sAxis0 | sAxisMax)) { limit[0] = fAxisMax[0]; } else if (areacode & (sAxis1 | sAxisMax)) { limit[0] = fAxisMax[1]; } } else { G4cerr << "WARNING - G4VTwistSurface::GetBoundaryAxis()" << G4endl << " areacode " << areacode << G4endl; G4Exception("G4VTwistSurface::GetBoundaryLimit()", "InvalidCondition", JustWarning, "Not located on a boundary!"); } } //===================================================================== //* SetBoundary ------------------------------------------------------- void G4VTwistSurface::SetBoundary(const G4int &axiscode, const G4ThreeVector &direction, const G4ThreeVector &x0, const G4int &boundarytype) { G4int code = (~sAxisMask) & axiscode; if ((code == (sAxis0 & sAxisMin)) || (code == (sAxis0 & sAxisMax)) || (code == (sAxis1 & sAxisMin)) || (code == (sAxis1 & sAxisMax))) { G4int i; G4bool done = false; for (i=0; i<4; i++) { if (fBoundaries[i].IsEmpty()) { fBoundaries[i].SetFields(axiscode, direction, x0, boundarytype); done = true; break; } } if (!done) { G4Exception("G4VTwistSurface::SetBoundary()", "InvalidCondition", FatalException, "Number of boundary exceeding 4!"); } } else { G4cerr << "ERROR - G4VTwistSurface::SetBoundary()" << G4endl << " invalid axiscode. axiscode = " << std::hex << axiscode << std::dec << G4endl; G4Exception("G4VTwistSurface::SetBoundary()", "InvalidCondition", FatalException, "Invalid axis-code."); } } //===================================================================== //* GetFace ----------------------------------------------------------- G4int G4VTwistSurface::GetFace( G4int i, G4int j, G4int m, G4int n, G4int iside ) { // this is the face mapping function // (i,j) -> face number if ( iside == 0 ) { return i * ( m - 1 ) + j ; } else if ( iside == 1 ) { return (m-1)*(m-1) + i*(m-1) + j ; } else if ( iside == 2 ) { return 2*(m-1)*(m-1) + i*(m-1) + j ; } else if ( iside == 3 ) { return 2*(m-1)*(m-1) + (n-1)*(m-1) + i*(m-1) + j ; } else if ( iside == 4 ) { return 2*(m-1)*(m-1) + 2*(n-1)*(m-1) + i*(m-1) + j ; } else if ( iside == 5 ) { return 2*(m-1)*(m-1) + 3*(n-1)*(m-1) + i*(m-1) + j ; } else { G4cerr << "ERROR - G4VTwistSurface::GetFace(): " << GetName() << G4endl << " Not correct side number! - " << G4endl << "iside is " << iside << " but should be " << "0,1,2,3,4 or 5" << "." << G4endl ; G4Exception("G4TwistSurface::G4GetFace()", "InvalidSetup", FatalException, "Not correct side number."); } return -1 ; // wrong face } //===================================================================== //* GetNode ----------------------------------------------------------- G4int G4VTwistSurface::GetNode( G4int i, G4int j, G4int m, G4int n, G4int iside ) { // this is the node mapping function // (i,j) -> node number // Depends on the side iside and the used meshing of the surface if ( iside == 0 ) { // lower endcap is mxm squared. // n = m return i * m + j ; } if ( iside == 1 ) { // upper endcap is mxm squared. Shift by m*m // n = m return m*m + i*m + j ; } else if ( iside == 2 ) { // front side. if ( i == 0 ) { return j ; } else if ( i == n-1 ) { return m*m + j ; } else { return 2*m*m + 4*(i-1)*(m-1) + j ; } } else if ( iside == 3 ) { // right side if ( i == 0 ) { return (j+1)*m - 1 ; } else if ( i == n-1 ) { return m*m + (j+1)*m - 1 ; } else { return 2*m*m + 4*(i-1)*(m-1) + (m-1) + j ; } } else if ( iside == 4 ) { // back side. if ( i == 0 ) { return m*m - 1 - j ; } // reversed order else if ( i == n-1 ) { return 2*m*m - 1 - j ; } // reversed order else { return 2*m*m + 4*(i-1)*(m-1) + 2*(m-1) + j ; // normal order } } else if ( iside == 5 ) { // left side if ( i == 0 ) { return m*m - (j+1)*m ; } // reversed order else if ( i == n-1) { return 2*m*m - (j+1)*m ; } // reverded order else { if ( j == m-1 ) { return 2*m*m + 4*(i-1)*(m-1) ; } // special case else { return 2*m*m + 4*(i-1)*(m-1) + 3*(m-1) + j ; } // normal order } } else { G4cerr << "ERROR - G4VTwistSurface::GetNode(): " << GetName() << G4endl << " Not correct side number! - " << G4endl << "iside is " << iside << " but should be " << "0,1,2,3,4 or 5" << "." << G4endl ; G4Exception("G4TwistSurface::G4GetNode()", "InvalidSetup", FatalException, "Not correct side number."); } return -1 ; // wrong node } //===================================================================== //* GetEdgeVisiblility ------------------------------------------------ G4int G4VTwistSurface::GetEdgeVisibility( G4int i, G4int j, G4int m, G4int n, G4int number, G4int orientation) { // clockwise filling -> positive orientation // counter clockwise filling -> negative orientation // // d C c // +------+ // | | // | | // | | // D | |B // | | // | | // | | // +------+ // a A b // // a = +--+ A = ---+ // b = --++ B = --+- // c = -++- C = -+-- // d = ++-- D = +--- // check first invisible faces if ( ( i>0 && i0 && j 3,2,1,0 if ( orientation < 0 ) { number = ( 3 - number ) ; } // check true edges if ( ( j>=1 && j<=m-3 ) ) { if ( i == 0 ) { // signs (A): ---+ return ( number == 3 ) ? 1 : -1 ; } else if ( i == n-2 ) { // signs (C): -+-- return ( number == 1 ) ? 1 : -1 ; } else { G4cerr << "ERROR - G4VTwistSurface::GetEdgeVisibliity(): " << GetName() << G4endl << " Not correct face number! - " << G4endl ; G4Exception("G4TwistSurface::G4GetEdgeVisibility()", "InvalidSetup", FatalException, "Not correct face number."); } } if ( ( i>=1 && i<=n-3 ) ) { if ( j == 0 ) { // signs (D): +--- return ( number == 0 ) ? 1 : -1 ; } else if ( j == m-2 ) { // signs (B): --+- return ( number == 2 ) ? 1 : -1 ; } else { G4cerr << "ERROR - G4VTwistSurface::GetEdgeVisibliity(): " << GetName() << G4endl << " Not correct face number! - " << G4endl ; G4Exception("G4TwistSurface::G4GetEdgeVisibility()", "InvalidSetup", FatalException, "Not correct face number."); } } // now the corners if ( i == 0 && j == 0 ) { // signs (a) : +--+ return ( number == 0 || number == 3 ) ? 1 : -1 ; } else if ( i == 0 && j == m-2 ) { // signs (b) : --++ return ( number == 2 || number == 3 ) ? 1 : -1 ; } else if ( i == n-2 && j == m-2 ) { // signs (c) : -++- return ( number == 1 || number == 2 ) ? 1 : -1 ; } else if ( i == n-2 && j == j ) { // signs (d) : ++-- return ( number == 0 || number == 1 ) ? 1 : -1 ; } else { G4cerr << "ERROR - G4VTwistSurface::GetEdgeVisibliity(): " << GetName() << G4endl << " Not correct face number! - " << G4endl ; G4Exception("G4TwistSurface::G4GetEdgeVisibility()", "InvalidSetup", FatalException, "Not correct face number."); } G4cerr << "ERROR - G4VTwistSurface::GetEdgeVisibliity(): " << GetName() << G4endl << " Not correct face number! - " << G4endl ; G4Exception("G4TwistSurface::G4GetEdgeVisibility()", "InvalidSetup", FatalException, "Not correct face number."); return 0 ; } //===================================================================== //* DebugPrint -------------------------------------------------------- void G4VTwistSurface::DebugPrint() const { G4ThreeVector A = fRot * GetCorner(sC0Min1Min) + fTrans; G4ThreeVector B = fRot * GetCorner(sC0Max1Min) + fTrans; G4ThreeVector C = fRot * GetCorner(sC0Max1Max) + fTrans; G4ThreeVector D = fRot * GetCorner(sC0Min1Max) + fTrans; G4cout << "/* G4VTwistSurface::DebugPrint():-------------------------------" << G4endl; G4cout << "/* Name = " << fName << G4endl; G4cout << "/* Axis = " << std::hex << fAxis[0] << " " << std::hex << fAxis[1] << " (0,1,2,3,5 = kXAxis,kYAxis,kZAxis,kRho,kPhi)" << std::dec << G4endl; G4cout << "/* BoundaryLimit(in local) fAxis0(min, max) = ("<