Geant4 Cross Reference |
1 // 1 // 2 // ******************************************* 2 // ******************************************************************** 3 // * License and Disclaimer 3 // * License and Disclaimer * 4 // * 4 // * * 5 // * The Geant4 software is copyright of th 5 // * The Geant4 software is copyright of the Copyright Holders of * 6 // * the Geant4 Collaboration. It is provided 6 // * the Geant4 Collaboration. It is provided under the terms and * 7 // * conditions of the Geant4 Software License 7 // * conditions of the Geant4 Software License, included in the file * 8 // * LICENSE and available at http://cern.ch/ 8 // * LICENSE and available at http://cern.ch/geant4/license . These * 9 // * include a list of copyright holders. 9 // * include a list of copyright holders. * 10 // * 10 // * * 11 // * Neither the authors of this software syst 11 // * Neither the authors of this software system, nor their employing * 12 // * institutes,nor the agencies providing fin 12 // * institutes,nor the agencies providing financial support for this * 13 // * work make any representation or warran 13 // * work make any representation or warranty, express or implied, * 14 // * regarding this software system or assum 14 // * regarding this software system or assume any liability for its * 15 // * use. Please see the license in the file 15 // * use. Please see the license in the file LICENSE and URL above * 16 // * for the full disclaimer and the limitatio 16 // * for the full disclaimer and the limitation of liability. * 17 // * 17 // * * 18 // * This code implementation is the result 18 // * This code implementation is the result of the scientific and * 19 // * technical work of the GEANT4 collaboratio 19 // * technical work of the GEANT4 collaboration. * 20 // * By using, copying, modifying or distri 20 // * By using, copying, modifying or distributing the software (or * 21 // * any work based on the software) you ag 21 // * any work based on the software) you agree to acknowledge its * 22 // * use in resulting scientific publicati 22 // * use in resulting scientific publications, and indicate your * 23 // * acceptance of all terms of the Geant4 Sof 23 // * acceptance of all terms of the Geant4 Software license. * 24 // ******************************************* 24 // ******************************************************************** 25 // 25 // 26 // Implementation of G4UGenericPolycone wrappe << 27 // 26 // 28 // 30.10.13 G.Cosmo, CERN << 27 // >> 28 // >> 29 // Implementation of G4UGenericPolycone wrapper class 29 // ------------------------------------------- 30 // -------------------------------------------------------------------- 30 31 31 #include "G4GenericPolycone.hh" 32 #include "G4GenericPolycone.hh" >> 33 #if 0 32 #include "G4UGenericPolycone.hh" 34 #include "G4UGenericPolycone.hh" 33 35 34 #if ( defined(G4GEOM_USE_USOLIDS) || defined(G 36 #if ( defined(G4GEOM_USE_USOLIDS) || defined(G4GEOM_USE_PARTIAL_USOLIDS) ) 35 37 36 #include "G4GeomTools.hh" 38 #include "G4GeomTools.hh" 37 #include "G4AffineTransform.hh" 39 #include "G4AffineTransform.hh" 38 #include "G4VPVParameterisation.hh" 40 #include "G4VPVParameterisation.hh" 39 #include "G4BoundingEnvelope.hh" 41 #include "G4BoundingEnvelope.hh" 40 42 41 #include "G4Polyhedron.hh" 43 #include "G4Polyhedron.hh" 42 44 43 using namespace CLHEP; 45 using namespace CLHEP; 44 46 45 ////////////////////////////////////////////// 47 //////////////////////////////////////////////////////////////////////// 46 // 48 // 47 // Constructor (generic parameters) 49 // Constructor (generic parameters) 48 // 50 // 49 G4UGenericPolycone::G4UGenericPolycone(const G << 51 G4UGenericPolycone::G4UGenericPolycone(const G4String& name, 50 G 52 G4double phiStart, 51 G 53 G4double phiTotal, 52 G 54 G4int numRZ, 53 const G 55 const G4double r[], 54 const G 56 const G4double z[] ) 55 : Base_t(name, phiStart, phiTotal, numRZ, r, << 57 : G4USolid(name, new UGenericPolycone(name, phiStart, phiTotal, numRZ, r, z)) 56 { << 58 { 57 wrStart = phiStart; while (wrStart < 0) wrSt << 58 wrDelta = phiTotal; << 59 if (wrDelta <= 0 || wrDelta >= twopi*(1-DBL_ << 60 { << 61 wrStart = 0; << 62 wrDelta = twopi; << 63 } << 64 rzcorners.resize(0); << 65 for (G4int i=0; i<numRZ; ++i) << 66 { << 67 rzcorners.emplace_back(r[i],z[i]); << 68 } << 69 std::vector<G4int> iout; << 70 G4GeomTools::RemoveRedundantVertices(rzcorne << 71 } 59 } 72 60 73 61 74 ////////////////////////////////////////////// 62 //////////////////////////////////////////////////////////////////////// 75 // 63 // 76 // Fake default constructor - sets only member 64 // Fake default constructor - sets only member data and allocates memory 77 // for usage restri 65 // for usage restricted to object persistency. 78 // 66 // 79 G4UGenericPolycone::G4UGenericPolycone(__void_ 67 G4UGenericPolycone::G4UGenericPolycone(__void__& a) 80 : Base_t(a) << 68 : G4USolid(a) 81 { 69 { 82 } 70 } 83 71 84 72 85 ////////////////////////////////////////////// 73 ////////////////////////////////////////////////////////////////////////// 86 // 74 // 87 // Destructor 75 // Destructor 88 // 76 // 89 G4UGenericPolycone::~G4UGenericPolycone() = de << 77 G4UGenericPolycone::~G4UGenericPolycone() >> 78 { >> 79 } 90 80 91 81 92 ////////////////////////////////////////////// 82 ////////////////////////////////////////////////////////////////////////// 93 // 83 // 94 // Copy constructor 84 // Copy constructor 95 // 85 // 96 G4UGenericPolycone::G4UGenericPolycone(const G << 86 G4UGenericPolycone::G4UGenericPolycone(const G4UGenericPolycone &source) 97 : Base_t(source) << 87 : G4USolid(source) 98 { 88 { 99 wrStart = source.wrStart; << 100 wrDelta = source.wrDelta; << 101 rzcorners = source.rzcorners; << 102 } 89 } 103 90 104 91 105 ////////////////////////////////////////////// 92 ////////////////////////////////////////////////////////////////////////// 106 // 93 // 107 // Assignment operator 94 // Assignment operator 108 // 95 // 109 G4UGenericPolycone& 96 G4UGenericPolycone& 110 G4UGenericPolycone::operator=(const G4UGeneric << 97 G4UGenericPolycone::operator=(const G4UGenericPolycone &source) 111 { 98 { 112 if (this == &source) return *this; 99 if (this == &source) return *this; 113 << 100 114 Base_t::operator=( source ); << 101 G4USolid::operator=( source ); 115 wrStart = source.wrStart; << 102 116 wrDelta = source.wrDelta; << 117 rzcorners = source.rzcorners; << 118 << 119 return *this; 103 return *this; 120 } 104 } 121 105 122 G4double G4UGenericPolycone::GetStartPhi() con 106 G4double G4UGenericPolycone::GetStartPhi() const 123 { 107 { 124 return wrStart; << 108 return GetShape()->GetStartPhi(); 125 } 109 } 126 G4double G4UGenericPolycone::GetEndPhi() const 110 G4double G4UGenericPolycone::GetEndPhi() const 127 { 111 { 128 return (wrStart + wrDelta); << 112 return GetShape()->GetEndPhi(); 129 } 113 } 130 G4double G4UGenericPolycone::GetSinStartPhi() 114 G4double G4UGenericPolycone::GetSinStartPhi() const 131 { 115 { 132 if (IsOpen()) return 0.; << 116 if (!GetShape()->IsOpen()) return 0; 133 G4double phi = GetStartPhi(); << 117 G4double phi = GetShape()->GetStartPhi(); 134 return std::sin(phi); 118 return std::sin(phi); 135 } 119 } 136 G4double G4UGenericPolycone::GetCosStartPhi() 120 G4double G4UGenericPolycone::GetCosStartPhi() const 137 { 121 { 138 if (IsOpen()) return 1.; << 122 if (!GetShape()->IsOpen()) return 1; 139 G4double phi = GetStartPhi(); << 123 G4double phi = GetShape()->GetStartPhi(); 140 return std::cos(phi); 124 return std::cos(phi); 141 } 125 } 142 G4double G4UGenericPolycone::GetSinEndPhi() co 126 G4double G4UGenericPolycone::GetSinEndPhi() const 143 { 127 { 144 if (IsOpen()) return 0.; << 128 if (!GetShape()->IsOpen()) return 0; 145 G4double phi = GetEndPhi(); << 129 G4double phi = GetShape()->GetEndPhi(); 146 return std::sin(phi); 130 return std::sin(phi); 147 } 131 } 148 G4double G4UGenericPolycone::GetCosEndPhi() co 132 G4double G4UGenericPolycone::GetCosEndPhi() const 149 { 133 { 150 if (IsOpen()) return 1.; << 134 if (!GetShape()->IsOpen()) return 1; 151 G4double phi = GetEndPhi(); << 135 G4double phi = GetShape()->GetEndPhi(); 152 return std::cos(phi); 136 return std::cos(phi); 153 } 137 } 154 G4bool G4UGenericPolycone::IsOpen() const 138 G4bool G4UGenericPolycone::IsOpen() const 155 { 139 { 156 return (wrDelta < twopi); << 140 return GetShape()->IsOpen(); 157 } 141 } 158 G4int G4UGenericPolycone::GetNumRZCorner() con 142 G4int G4UGenericPolycone::GetNumRZCorner() const 159 { 143 { 160 return rzcorners.size(); << 144 return GetShape()->GetNumRZCorner(); 161 } 145 } 162 G4PolyconeSideRZ G4UGenericPolycone::GetCorner 146 G4PolyconeSideRZ G4UGenericPolycone::GetCorner(G4int index) const 163 { 147 { 164 G4TwoVector rz = rzcorners.at(index); << 148 UPolyconeSideRZ pside = GetShape()->GetCorner(index); 165 G4PolyconeSideRZ psiderz = { rz.x(), rz.y() << 149 G4PolyconeSideRZ psiderz = { pside.r, pside.z }; 166 150 167 return psiderz; 151 return psiderz; 168 } 152 } 169 153 170 ////////////////////////////////////////////// 154 ////////////////////////////////////////////////////////////////////////// 171 // 155 // 172 // Make a clone of the object << 173 << 174 G4VSolid* G4UGenericPolycone::Clone() const << 175 { << 176 return new G4UGenericPolycone(*this); << 177 } << 178 << 179 ////////////////////////////////////////////// << 180 // << 181 // Get bounding box 156 // Get bounding box 182 157 183 void 158 void 184 G4UGenericPolycone::BoundingLimits(G4ThreeVect 159 G4UGenericPolycone::BoundingLimits(G4ThreeVector& pMin, 185 G4ThreeVect 160 G4ThreeVector& pMax) const 186 { 161 { 187 G4double rmin = kInfinity, rmax = -kInfinity 162 G4double rmin = kInfinity, rmax = -kInfinity; 188 G4double zmin = kInfinity, zmax = -kInfinity 163 G4double zmin = kInfinity, zmax = -kInfinity; 189 164 190 for (G4int i=0; i<GetNumRZCorner(); ++i) 165 for (G4int i=0; i<GetNumRZCorner(); ++i) 191 { 166 { 192 G4PolyconeSideRZ corner = GetCorner(i); 167 G4PolyconeSideRZ corner = GetCorner(i); 193 if (corner.r < rmin) rmin = corner.r; 168 if (corner.r < rmin) rmin = corner.r; 194 if (corner.r > rmax) rmax = corner.r; 169 if (corner.r > rmax) rmax = corner.r; 195 if (corner.z < zmin) zmin = corner.z; 170 if (corner.z < zmin) zmin = corner.z; 196 if (corner.z > zmax) zmax = corner.z; 171 if (corner.z > zmax) zmax = corner.z; 197 } 172 } 198 173 199 if (IsOpen()) 174 if (IsOpen()) 200 { 175 { 201 G4TwoVector vmin,vmax; 176 G4TwoVector vmin,vmax; 202 G4GeomTools::DiskExtent(rmin,rmax, 177 G4GeomTools::DiskExtent(rmin,rmax, 203 GetSinStartPhi(),G 178 GetSinStartPhi(),GetCosStartPhi(), 204 GetSinEndPhi(),Get 179 GetSinEndPhi(),GetCosEndPhi(), 205 vmin,vmax); 180 vmin,vmax); 206 pMin.set(vmin.x(),vmin.y(),zmin); 181 pMin.set(vmin.x(),vmin.y(),zmin); 207 pMax.set(vmax.x(),vmax.y(),zmax); 182 pMax.set(vmax.x(),vmax.y(),zmax); 208 } 183 } 209 else 184 else 210 { 185 { 211 pMin.set(-rmax,-rmax, zmin); 186 pMin.set(-rmax,-rmax, zmin); 212 pMax.set( rmax, rmax, zmax); 187 pMax.set( rmax, rmax, zmax); 213 } 188 } 214 189 215 // Check correctness of the bounding box 190 // Check correctness of the bounding box 216 // 191 // 217 if (pMin.x() >= pMax.x() || pMin.y() >= pMax 192 if (pMin.x() >= pMax.x() || pMin.y() >= pMax.y() || pMin.z() >= pMax.z()) 218 { 193 { 219 std::ostringstream message; 194 std::ostringstream message; 220 message << "Bad bounding box (min >= max) 195 message << "Bad bounding box (min >= max) for solid: " 221 << GetName() << " !" 196 << GetName() << " !" 222 << "\npMin = " << pMin 197 << "\npMin = " << pMin 223 << "\npMax = " << pMax; 198 << "\npMax = " << pMax; 224 G4Exception("G4UGenericPolycone::BoundingL 199 G4Exception("G4UGenericPolycone::BoundingLimits()", "GeomMgt0001", 225 JustWarning, message); 200 JustWarning, message); 226 StreamInfo(G4cout); 201 StreamInfo(G4cout); 227 } 202 } 228 } 203 } 229 204 230 ////////////////////////////////////////////// 205 ////////////////////////////////////////////////////////////////////////// 231 // 206 // 232 // Calculate extent under transform and specif 207 // Calculate extent under transform and specified limit 233 208 234 G4bool 209 G4bool 235 G4UGenericPolycone::CalculateExtent(const EAxi 210 G4UGenericPolycone::CalculateExtent(const EAxis pAxis, 236 const G4Vo 211 const G4VoxelLimits& pVoxelLimit, 237 const G4Af 212 const G4AffineTransform& pTransform, 238 G4do 213 G4double& pMin, G4double& pMax) const 239 { 214 { 240 G4ThreeVector bmin, bmax; 215 G4ThreeVector bmin, bmax; 241 G4bool exist; 216 G4bool exist; 242 217 243 // Check bounding box (bbox) 218 // Check bounding box (bbox) 244 // 219 // 245 BoundingLimits(bmin,bmax); 220 BoundingLimits(bmin,bmax); 246 G4BoundingEnvelope bbox(bmin,bmax); 221 G4BoundingEnvelope bbox(bmin,bmax); 247 #ifdef G4BBOX_EXTENT 222 #ifdef G4BBOX_EXTENT 248 return bbox.CalculateExtent(pAxis,pVoxelLimi << 223 if (true) return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax); 249 #endif 224 #endif 250 if (bbox.BoundingBoxVsVoxelLimits(pAxis,pVox 225 if (bbox.BoundingBoxVsVoxelLimits(pAxis,pVoxelLimit,pTransform,pMin,pMax)) 251 { 226 { 252 return exist = pMin < pMax; << 227 return exist = (pMin < pMax) ? true : false; 253 } 228 } 254 229 255 // To find the extent, RZ contour of the pol 230 // To find the extent, RZ contour of the polycone is subdivided 256 // in triangles. The extent is calculated as 231 // in triangles. The extent is calculated as cumulative extent of 257 // all sub-polycones formed by rotation of t 232 // all sub-polycones formed by rotation of triangles around Z 258 // 233 // 259 G4TwoVectorList contourRZ; 234 G4TwoVectorList contourRZ; 260 G4TwoVectorList triangles; 235 G4TwoVectorList triangles; 261 G4double eminlim = pVoxelLimit.GetMinExtent( 236 G4double eminlim = pVoxelLimit.GetMinExtent(pAxis); 262 G4double emaxlim = pVoxelLimit.GetMaxExtent( 237 G4double emaxlim = pVoxelLimit.GetMaxExtent(pAxis); 263 238 264 // get RZ contour, ensure anticlockwise orde 239 // get RZ contour, ensure anticlockwise order of corners 265 for (G4int i=0; i<GetNumRZCorner(); ++i) 240 for (G4int i=0; i<GetNumRZCorner(); ++i) 266 { 241 { 267 G4PolyconeSideRZ corner = GetCorner(i); 242 G4PolyconeSideRZ corner = GetCorner(i); 268 contourRZ.emplace_back(corner.r,corner.z); << 243 contourRZ.push_back(G4TwoVector(corner.r,corner.z)); 269 } 244 } 270 G4double area = G4GeomTools::PolygonArea(con 245 G4double area = G4GeomTools::PolygonArea(contourRZ); 271 if (area < 0.) std::reverse(contourRZ.begin( 246 if (area < 0.) std::reverse(contourRZ.begin(),contourRZ.end()); 272 247 273 // triangulate RZ countour 248 // triangulate RZ countour 274 if (!G4GeomTools::TriangulatePolygon(contour 249 if (!G4GeomTools::TriangulatePolygon(contourRZ,triangles)) 275 { 250 { 276 std::ostringstream message; 251 std::ostringstream message; 277 message << "Triangulation of RZ contour ha 252 message << "Triangulation of RZ contour has failed for solid: " 278 << GetName() << " !" 253 << GetName() << " !" 279 << "\nExtent has been calculated u 254 << "\nExtent has been calculated using boundary box"; 280 G4Exception("G4UGenericPolycone::Calculate 255 G4Exception("G4UGenericPolycone::CalculateExtent()", 281 "GeomMgt1002", JustWarning, me 256 "GeomMgt1002", JustWarning, message); 282 return bbox.CalculateExtent(pAxis,pVoxelLi 257 return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax); 283 } 258 } 284 259 285 // set trigonometric values 260 // set trigonometric values 286 const G4int NSTEPS = 24; // numbe 261 const G4int NSTEPS = 24; // number of steps for whole circle 287 G4double astep = twopi/NSTEPS; // max a 262 G4double astep = twopi/NSTEPS; // max angle for one step 288 263 289 G4double sphi = GetStartPhi(); 264 G4double sphi = GetStartPhi(); 290 G4double ephi = GetEndPhi(); 265 G4double ephi = GetEndPhi(); 291 G4double dphi = IsOpen() ? ephi-sphi : two 266 G4double dphi = IsOpen() ? ephi-sphi : twopi; 292 G4int ksteps = (dphi <= astep) ? 1 : (G4i 267 G4int ksteps = (dphi <= astep) ? 1 : (G4int)((dphi-deg)/astep) + 1; 293 G4double ang = dphi/ksteps; 268 G4double ang = dphi/ksteps; 294 269 295 G4double sinHalf = std::sin(0.5*ang); 270 G4double sinHalf = std::sin(0.5*ang); 296 G4double cosHalf = std::cos(0.5*ang); 271 G4double cosHalf = std::cos(0.5*ang); 297 G4double sinStep = 2.*sinHalf*cosHalf; 272 G4double sinStep = 2.*sinHalf*cosHalf; 298 G4double cosStep = 1. - 2.*sinHalf*sinHalf; 273 G4double cosStep = 1. - 2.*sinHalf*sinHalf; 299 274 300 G4double sinStart = GetSinStartPhi(); 275 G4double sinStart = GetSinStartPhi(); 301 G4double cosStart = GetCosStartPhi(); 276 G4double cosStart = GetCosStartPhi(); 302 G4double sinEnd = GetSinEndPhi(); 277 G4double sinEnd = GetSinEndPhi(); 303 G4double cosEnd = GetCosEndPhi(); 278 G4double cosEnd = GetCosEndPhi(); 304 279 305 // define vectors and arrays 280 // define vectors and arrays 306 std::vector<const G4ThreeVectorList *> polyg 281 std::vector<const G4ThreeVectorList *> polygons; 307 polygons.resize(ksteps+2); 282 polygons.resize(ksteps+2); 308 G4ThreeVectorList pols[NSTEPS+2]; 283 G4ThreeVectorList pols[NSTEPS+2]; 309 for (G4int k=0; k<ksteps+2; ++k) pols[k].res 284 for (G4int k=0; k<ksteps+2; ++k) pols[k].resize(6); 310 for (G4int k=0; k<ksteps+2; ++k) polygons[k] 285 for (G4int k=0; k<ksteps+2; ++k) polygons[k] = &pols[k]; 311 G4double r0[6],z0[6]; // contour with origin 286 G4double r0[6],z0[6]; // contour with original edges of triangle 312 G4double r1[6]; // shifted radii of ex 287 G4double r1[6]; // shifted radii of external edges of triangle 313 288 314 // main loop along triangles 289 // main loop along triangles 315 pMin = kInfinity; 290 pMin = kInfinity; 316 pMax =-kInfinity; 291 pMax =-kInfinity; 317 G4int ntria = triangles.size()/3; 292 G4int ntria = triangles.size()/3; 318 for (G4int i=0; i<ntria; ++i) 293 for (G4int i=0; i<ntria; ++i) 319 { 294 { 320 G4int i3 = i*3; 295 G4int i3 = i*3; 321 for (G4int k=0; k<3; ++k) 296 for (G4int k=0; k<3; ++k) 322 { 297 { 323 G4int e0 = i3+k, e1 = (k<2) ? e0+1 : i3; 298 G4int e0 = i3+k, e1 = (k<2) ? e0+1 : i3; 324 G4int k2 = k*2; 299 G4int k2 = k*2; 325 // set contour with original edges of tr 300 // set contour with original edges of triangle 326 r0[k2+0] = triangles[e0].x(); z0[k2+0] = 301 r0[k2+0] = triangles[e0].x(); z0[k2+0] = triangles[e0].y(); 327 r0[k2+1] = triangles[e1].x(); z0[k2+1] = 302 r0[k2+1] = triangles[e1].x(); z0[k2+1] = triangles[e1].y(); 328 // set shifted radii 303 // set shifted radii 329 r1[k2+0] = r0[k2+0]; 304 r1[k2+0] = r0[k2+0]; 330 r1[k2+1] = r0[k2+1]; 305 r1[k2+1] = r0[k2+1]; 331 if (z0[k2+1] - z0[k2+0] <= 0) continue; 306 if (z0[k2+1] - z0[k2+0] <= 0) continue; 332 r1[k2+0] /= cosHalf; 307 r1[k2+0] /= cosHalf; 333 r1[k2+1] /= cosHalf; 308 r1[k2+1] /= cosHalf; 334 } 309 } 335 310 336 // rotate countour, set sequence of 6-side 311 // rotate countour, set sequence of 6-sided polygons 337 G4double sinCur = sinStart*cosHalf + cosSt 312 G4double sinCur = sinStart*cosHalf + cosStart*sinHalf; 338 G4double cosCur = cosStart*cosHalf - sinSt 313 G4double cosCur = cosStart*cosHalf - sinStart*sinHalf; 339 for (G4int j=0; j<6; ++j) 314 for (G4int j=0; j<6; ++j) 340 { 315 { 341 pols[0][j].set(r0[j]*cosStart,r0[j]*sinS 316 pols[0][j].set(r0[j]*cosStart,r0[j]*sinStart,z0[j]); 342 } 317 } 343 for (G4int k=1; k<ksteps+1; ++k) 318 for (G4int k=1; k<ksteps+1; ++k) 344 { 319 { 345 for (G4int j=0; j<6; ++j) 320 for (G4int j=0; j<6; ++j) 346 { 321 { 347 pols[k][j].set(r1[j]*cosCur,r1[j]*sinC 322 pols[k][j].set(r1[j]*cosCur,r1[j]*sinCur,z0[j]); 348 } 323 } 349 G4double sinTmp = sinCur; 324 G4double sinTmp = sinCur; 350 sinCur = sinCur*cosStep + cosCur*sinStep 325 sinCur = sinCur*cosStep + cosCur*sinStep; 351 cosCur = cosCur*cosStep - sinTmp*sinStep 326 cosCur = cosCur*cosStep - sinTmp*sinStep; 352 } 327 } 353 for (G4int j=0; j<6; ++j) 328 for (G4int j=0; j<6; ++j) 354 { 329 { 355 pols[ksteps+1][j].set(r0[j]*cosEnd,r0[j] 330 pols[ksteps+1][j].set(r0[j]*cosEnd,r0[j]*sinEnd,z0[j]); 356 } 331 } 357 332 358 // set sub-envelope and adjust extent 333 // set sub-envelope and adjust extent 359 G4double emin,emax; 334 G4double emin,emax; 360 G4BoundingEnvelope benv(polygons); 335 G4BoundingEnvelope benv(polygons); 361 if (!benv.CalculateExtent(pAxis,pVoxelLimi 336 if (!benv.CalculateExtent(pAxis,pVoxelLimit,pTransform,emin,emax)) continue; 362 if (emin < pMin) pMin = emin; 337 if (emin < pMin) pMin = emin; 363 if (emax > pMax) pMax = emax; 338 if (emax > pMax) pMax = emax; 364 if (eminlim > pMin && emaxlim < pMax) retu 339 if (eminlim > pMin && emaxlim < pMax) return true; // max possible extent 365 } 340 } 366 return (pMin < pMax); 341 return (pMin < pMax); 367 } 342 } 368 343 369 ////////////////////////////////////////////// 344 //////////////////////////////////////////////////////////////////////// 370 // 345 // 371 // CreatePolyhedron 346 // CreatePolyhedron 372 347 373 G4Polyhedron* G4UGenericPolycone::CreatePolyhe 348 G4Polyhedron* G4UGenericPolycone::CreatePolyhedron() const 374 { 349 { 375 return new G4PolyhedronPcon(wrStart, wrDelta << 350 >> 351 >> 352 // The following code prepares for: >> 353 // HepPolyhedron::createPolyhedron(int Nnodes, int Nfaces, >> 354 // const double xyz[][3], >> 355 // const int faces_vec[][4]) >> 356 // Here is an extract from the header file HepPolyhedron.h: >> 357 /** >> 358 * Creates user defined polyhedron. >> 359 * This function allows to the user to define arbitrary polyhedron. >> 360 * The faces of the polyhedron should be either triangles or planar >> 361 * quadrilateral. Nodes of a face are defined by indexes pointing to >> 362 * the elements in the xyz array. Numeration of the elements in the >> 363 * array starts from 1 (like in fortran). The indexes can be positive >> 364 * or negative. Negative sign means that the corresponding edge is >> 365 * invisible. The normal of the face should be directed to exterior >> 366 * of the polyhedron. >> 367 * >> 368 * @param Nnodes number of nodes >> 369 * @param Nfaces number of faces >> 370 * @param xyz nodes >> 371 * @param faces_vec faces (quadrilaterals or triangles) >> 372 * @return status of the operation - is non-zero in case of problem >> 373 */ >> 374 const G4int numSide = >> 375 G4int(G4Polyhedron::GetNumberOfRotationSteps() >> 376 * (GetEndPhi() - GetStartPhi()) / twopi) + 1; >> 377 G4int nNodes; >> 378 G4int nFaces; >> 379 typedef G4double double3[3]; >> 380 double3* xyz; >> 381 typedef G4int int4[4]; >> 382 int4* faces_vec; >> 383 if (IsOpen()) >> 384 { >> 385 // Triangulate open ends. Simple ear-chopping algorithm... >> 386 // I'm not sure how robust this algorithm is (J.Allison). >> 387 // >> 388 std::vector<G4bool> chopped(GetNumRZCorner(), false); >> 389 std::vector<G4int*> triQuads; >> 390 G4int remaining = GetNumRZCorner(); >> 391 G4int iStarter = 0; >> 392 while (remaining >= 3) // Loop checking, 13.08.2015, G.Cosmo >> 393 { >> 394 // Find unchopped corners... >> 395 // >> 396 G4int A = -1, B = -1, C = -1; >> 397 G4int iStepper = iStarter; >> 398 do // Loop checking, 13.08.2015, G.Cosmo >> 399 { >> 400 if (A < 0) { A = iStepper; } >> 401 else if (B < 0) { B = iStepper; } >> 402 else if (C < 0) { C = iStepper; } >> 403 do // Loop checking, 13.08.2015, G.Cosmo >> 404 { >> 405 if (++iStepper >= GetNumRZCorner()) { iStepper = 0; } >> 406 } >> 407 while (chopped[iStepper]); >> 408 } >> 409 while (C < 0 && iStepper != iStarter); >> 410 >> 411 // Check triangle at B is pointing outward (an "ear"). >> 412 // Sign of z cross product determines... >> 413 // >> 414 G4double BAr = GetCorner(A).r - GetCorner(B).r; >> 415 G4double BAz = GetCorner(A).z - GetCorner(B).z; >> 416 G4double BCr = GetCorner(C).r - GetCorner(B).r; >> 417 G4double BCz = GetCorner(C).z - GetCorner(B).z; >> 418 if (BAr * BCz - BAz * BCr < kCarTolerance) >> 419 { >> 420 G4int* tq = new G4int[3]; >> 421 tq[0] = A + 1; >> 422 tq[1] = B + 1; >> 423 tq[2] = C + 1; >> 424 triQuads.push_back(tq); >> 425 chopped[B] = true; >> 426 --remaining; >> 427 } >> 428 else >> 429 { >> 430 do // Loop checking, 13.08.2015, G.Cosmo >> 431 { >> 432 if (++iStarter >= GetNumRZCorner()) { iStarter = 0; } >> 433 } >> 434 while (chopped[iStarter]); >> 435 } >> 436 } >> 437 // Transfer to faces... >> 438 // >> 439 nNodes = (numSide + 1) * GetNumRZCorner(); >> 440 nFaces = numSide * GetNumRZCorner() + 2 * triQuads.size(); >> 441 faces_vec = new int4[nFaces]; >> 442 G4int iface = 0; >> 443 G4int addition = GetNumRZCorner() * numSide; >> 444 G4int d = GetNumRZCorner() - 1; >> 445 for (G4int iEnd = 0; iEnd < 2; ++iEnd) >> 446 { >> 447 for (size_t i = 0; i < triQuads.size(); ++i) >> 448 { >> 449 // Negative for soft/auxiliary/normally invisible edges... >> 450 // >> 451 G4int a, b, c; >> 452 if (iEnd == 0) >> 453 { >> 454 a = triQuads[i][0]; >> 455 b = triQuads[i][1]; >> 456 c = triQuads[i][2]; >> 457 } >> 458 else >> 459 { >> 460 a = triQuads[i][0] + addition; >> 461 b = triQuads[i][2] + addition; >> 462 c = triQuads[i][1] + addition; >> 463 } >> 464 G4int ab = std::abs(b - a); >> 465 G4int bc = std::abs(c - b); >> 466 G4int ca = std::abs(a - c); >> 467 faces_vec[iface][0] = (ab == 1 || ab == d)? a: -a; >> 468 faces_vec[iface][1] = (bc == 1 || bc == d)? b: -b; >> 469 faces_vec[iface][2] = (ca == 1 || ca == d)? c: -c; >> 470 faces_vec[iface][3] = 0; >> 471 ++iface; >> 472 } >> 473 } >> 474 >> 475 // Continue with sides... >> 476 >> 477 xyz = new double3[nNodes]; >> 478 const G4double dPhi = (GetEndPhi() - GetStartPhi()) / numSide; >> 479 G4double phi = GetStartPhi(); >> 480 G4int ixyz = 0; >> 481 for (G4int iSide = 0; iSide < numSide; ++iSide) >> 482 { >> 483 for (G4int iCorner = 0; iCorner < GetNumRZCorner(); ++iCorner) >> 484 { >> 485 xyz[ixyz][0] = GetCorner(iCorner).r * std::cos(phi); >> 486 xyz[ixyz][1] = GetCorner(iCorner).r * std::sin(phi); >> 487 xyz[ixyz][2] = GetCorner(iCorner).z; >> 488 if (iSide == 0) // startPhi >> 489 { >> 490 if (iCorner < GetNumRZCorner() - 1) >> 491 { >> 492 faces_vec[iface][0] = ixyz + 1; >> 493 faces_vec[iface][1] = -(ixyz + GetNumRZCorner() + 1); >> 494 faces_vec[iface][2] = ixyz + GetNumRZCorner() + 2; >> 495 faces_vec[iface][3] = ixyz + 2; >> 496 } >> 497 else >> 498 { >> 499 faces_vec[iface][0] = ixyz + 1; >> 500 faces_vec[iface][1] = -(ixyz + GetNumRZCorner() + 1); >> 501 faces_vec[iface][2] = ixyz + 2; >> 502 faces_vec[iface][3] = ixyz - GetNumRZCorner() + 2; >> 503 } >> 504 } >> 505 else if (iSide == numSide - 1) // endPhi >> 506 { >> 507 if (iCorner < GetNumRZCorner() - 1) >> 508 { >> 509 faces_vec[iface][0] = ixyz + 1; >> 510 faces_vec[iface][1] = ixyz + GetNumRZCorner() + 1; >> 511 faces_vec[iface][2] = ixyz + GetNumRZCorner() + 2; >> 512 faces_vec[iface][3] = -(ixyz + 2); >> 513 } >> 514 else >> 515 { >> 516 faces_vec[iface][0] = ixyz + 1; >> 517 faces_vec[iface][1] = ixyz + GetNumRZCorner() + 1; >> 518 faces_vec[iface][2] = ixyz + 2; >> 519 faces_vec[iface][3] = -(ixyz - GetNumRZCorner() + 2); >> 520 } >> 521 } >> 522 else >> 523 { >> 524 if (iCorner < GetNumRZCorner() - 1) >> 525 { >> 526 faces_vec[iface][0] = ixyz + 1; >> 527 faces_vec[iface][1] = -(ixyz + GetNumRZCorner() + 1); >> 528 faces_vec[iface][2] = ixyz + GetNumRZCorner() + 2; >> 529 faces_vec[iface][3] = -(ixyz + 2); >> 530 } >> 531 else >> 532 { >> 533 faces_vec[iface][0] = ixyz + 1; >> 534 faces_vec[iface][1] = -(ixyz + GetNumRZCorner() + 1); >> 535 faces_vec[iface][2] = ixyz + 2; >> 536 faces_vec[iface][3] = -(ixyz - GetNumRZCorner() + 2); >> 537 } >> 538 } >> 539 ++iface; >> 540 ++ixyz; >> 541 } >> 542 phi += dPhi; >> 543 } >> 544 >> 545 // Last corners... >> 546 >> 547 for (G4int iCorner = 0; iCorner < GetNumRZCorner(); ++iCorner) >> 548 { >> 549 xyz[ixyz][0] = GetCorner(iCorner).r * std::cos(phi); >> 550 xyz[ixyz][1] = GetCorner(iCorner).r * std::sin(phi); >> 551 xyz[ixyz][2] = GetCorner(iCorner).z; >> 552 ++ixyz; >> 553 } >> 554 } >> 555 else // !phiIsOpen - i.e., a complete 360 degrees. >> 556 { >> 557 nNodes = numSide * GetNumRZCorner(); >> 558 nFaces = numSide * GetNumRZCorner();; >> 559 xyz = new double3[nNodes]; >> 560 faces_vec = new int4[nFaces]; >> 561 const G4double dPhi = (GetEndPhi() - GetStartPhi()) / numSide; >> 562 G4double phi = GetStartPhi(); >> 563 G4int ixyz = 0, iface = 0; >> 564 for (G4int iSide = 0; iSide < numSide; ++iSide) >> 565 { >> 566 for (G4int iCorner = 0; iCorner < GetNumRZCorner(); ++iCorner) >> 567 { >> 568 xyz[ixyz][0] = GetCorner(iCorner).r * std::cos(phi); >> 569 xyz[ixyz][1] = GetCorner(iCorner).r * std::sin(phi); >> 570 xyz[ixyz][2] = GetCorner(iCorner).z; >> 571 >> 572 if (iSide < numSide - 1) >> 573 { >> 574 if (iCorner < GetNumRZCorner() - 1) >> 575 { >> 576 faces_vec[iface][0] = ixyz + 1; >> 577 faces_vec[iface][1] = -(ixyz + GetNumRZCorner() + 1); >> 578 faces_vec[iface][2] = ixyz + GetNumRZCorner() + 2; >> 579 faces_vec[iface][3] = -(ixyz + 2); >> 580 } >> 581 else >> 582 { >> 583 faces_vec[iface][0] = ixyz + 1; >> 584 faces_vec[iface][1] = -(ixyz + GetNumRZCorner() + 1); >> 585 faces_vec[iface][2] = ixyz + 2; >> 586 faces_vec[iface][3] = -(ixyz - GetNumRZCorner() + 2); >> 587 } >> 588 } >> 589 else // Last side joins ends... >> 590 { >> 591 if (iCorner < GetNumRZCorner() - 1) >> 592 { >> 593 faces_vec[iface][0] = ixyz + 1; >> 594 faces_vec[iface][1] = -(ixyz + GetNumRZCorner() - nFaces + 1); >> 595 faces_vec[iface][2] = ixyz + GetNumRZCorner() - nFaces + 2; >> 596 faces_vec[iface][3] = -(ixyz + 2); >> 597 } >> 598 else >> 599 { >> 600 faces_vec[iface][0] = ixyz + 1; >> 601 faces_vec[iface][1] = -(ixyz - nFaces + GetNumRZCorner() + 1); >> 602 faces_vec[iface][2] = ixyz - nFaces + 2; >> 603 faces_vec[iface][3] = -(ixyz - GetNumRZCorner() + 2); >> 604 } >> 605 } >> 606 ++ixyz; >> 607 ++iface; >> 608 } >> 609 phi += dPhi; >> 610 } >> 611 } >> 612 G4Polyhedron* polyhedron = new G4Polyhedron; >> 613 G4int prob = polyhedron->createPolyhedron(nNodes, nFaces, xyz, faces_vec); >> 614 delete [] faces_vec; >> 615 delete [] xyz; >> 616 if (prob) >> 617 { >> 618 std::ostringstream message; >> 619 message << "Problem creating G4Polyhedron for: " << GetName(); >> 620 G4Exception("G4GenericPolycone::CreatePolyhedron()", "GeomSolids1002", >> 621 JustWarning, message); >> 622 delete polyhedron; >> 623 return 0; >> 624 } >> 625 else >> 626 { >> 627 return polyhedron; >> 628 } 376 } 629 } 377 630 378 #endif // G4GEOM_USE_USOLIDS 631 #endif // G4GEOM_USE_USOLIDS >> 632 #endif 379 633