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 G4UPolyhedra wrapper clas << 27 // 26 // 28 // 31.10.13 G.Cosmo, CERN << 27 // $Id:$ >> 28 // >> 29 // Implementation of G4UPolycone wrapper class 29 // ------------------------------------------- 30 // -------------------------------------------------------------------- 30 31 31 #include "G4Polyhedra.hh" 32 #include "G4Polyhedra.hh" 32 #include "G4UPolyhedra.hh" 33 #include "G4UPolyhedra.hh" 33 34 34 #if ( defined(G4GEOM_USE_USOLIDS) || defined(G 35 #if ( defined(G4GEOM_USE_USOLIDS) || defined(G4GEOM_USE_PARTIAL_USOLIDS) ) 35 36 36 #include "G4GeomTools.hh" << 37 #include "G4GeometryTolerance.hh" << 38 #include "G4AffineTransform.hh" << 39 #include "G4VPVParameterisation.hh" 37 #include "G4VPVParameterisation.hh" 40 #include "G4BoundingEnvelope.hh" << 41 38 42 using namespace CLHEP; << 39 using CLHEP::twopi; 43 40 44 ////////////////////////////////////////////// 41 //////////////////////////////////////////////////////////////////////// 45 // 42 // 46 // Constructor (GEANT3 style parameters) 43 // Constructor (GEANT3 style parameters) 47 // 44 // 48 // GEANT3 PGON radii are specified in the dist 45 // GEANT3 PGON radii are specified in the distance to the norm of each face. 49 // << 46 // 50 G4UPolyhedra::G4UPolyhedra(const G4String& nam << 47 G4UPolyhedra::G4UPolyhedra(const G4String& name, 51 G4double phiS 48 G4double phiStart, 52 G4double phiT 49 G4double phiTotal, 53 G4int numSide << 50 G4int numSide, 54 G4int numZPla 51 G4int numZPlanes, 55 const G4double zPla 52 const G4double zPlane[], 56 const G4double rInn 53 const G4double rInner[], 57 const G4double rOut 54 const G4double rOuter[] ) 58 : Base_t(name, phiStart, phiTotal, numSide, << 55 : G4USolid(name, new UPolyhedra(name,phiStart, phiTotal, numSide, 59 numZPlanes, zPlane, rInner, rOuter) << 56 numZPlanes, zPlane, rInner, rOuter)) 60 { 57 { 61 fGenericPgon = false; << 62 SetOriginalParameters(); << 63 wrStart = phiStart; << 64 while (wrStart < 0) << 65 { << 66 wrStart += twopi; << 67 } << 68 wrDelta = phiTotal; << 69 if (wrDelta <= 0. || wrDelta >= twopi*(1-DBL << 70 { << 71 wrDelta = twopi; << 72 } << 73 wrNumSide = numSide; << 74 G4double convertRad = 1./std::cos(0.5*wrDelt << 75 rzcorners.resize(0); << 76 for (G4int i=0; i<numZPlanes; ++i) << 77 { << 78 G4double z = zPlane[i]; << 79 G4double r = rOuter[i]*convertRad; << 80 rzcorners.emplace_back(r,z); << 81 } << 82 for (G4int i=numZPlanes-1; i>=0; --i) << 83 { << 84 G4double z = zPlane[i]; << 85 G4double r = rInner[i]*convertRad; << 86 rzcorners.emplace_back(r,z); << 87 } << 88 std::vector<G4int> iout; << 89 G4GeomTools::RemoveRedundantVertices(rzcorne << 90 } 58 } 91 59 92 60 93 ////////////////////////////////////////////// 61 //////////////////////////////////////////////////////////////////////// 94 // 62 // 95 // Constructor (generic parameters) 63 // Constructor (generic parameters) 96 // 64 // 97 G4UPolyhedra::G4UPolyhedra(const G4String& nam << 65 G4UPolyhedra::G4UPolyhedra(const G4String& name, 98 G4double phiS 66 G4double phiStart, 99 G4double phiT 67 G4double phiTotal, 100 G4int numS << 68 G4int numSide, 101 G4int numR 69 G4int numRZ, 102 const G4double r[], 70 const G4double r[], 103 const G4double z[] 71 const G4double z[] ) 104 : Base_t(name, phiStart, phiTotal, numSide, << 72 : G4USolid(name, new UPolyhedra(name, phiStart, phiTotal, numSide, 105 { << 73 numRZ, r, z)) 106 fGenericPgon = true; << 74 { 107 SetOriginalParameters(); << 108 wrStart = phiStart; << 109 while (wrStart < 0.) << 110 { << 111 wrStart += twopi; << 112 } << 113 wrDelta = phiTotal; << 114 if (wrDelta <= 0. || wrDelta >= twopi*(1-DBL << 115 { << 116 wrDelta = twopi; << 117 } << 118 wrNumSide = numSide; << 119 rzcorners.resize(0); << 120 for (G4int i=0; i<numRZ; ++i) << 121 { << 122 rzcorners.emplace_back(r[i],z[i]); << 123 } << 124 std::vector<G4int> iout; << 125 G4GeomTools::RemoveRedundantVertices(rzcorne << 126 } 75 } 127 76 128 77 129 ////////////////////////////////////////////// 78 //////////////////////////////////////////////////////////////////////// 130 // 79 // 131 // Fake default constructor - sets only member 80 // Fake default constructor - sets only member data and allocates memory 132 // for usage restri 81 // for usage restricted to object persistency. 133 // 82 // 134 G4UPolyhedra::G4UPolyhedra( __void__& a ) 83 G4UPolyhedra::G4UPolyhedra( __void__& a ) 135 : Base_t(a) << 84 : G4USolid(a) 136 { 85 { 137 } 86 } 138 87 139 88 140 ////////////////////////////////////////////// 89 //////////////////////////////////////////////////////////////////////// 141 // 90 // 142 // Destructor 91 // Destructor 143 // 92 // 144 G4UPolyhedra::~G4UPolyhedra() = default; << 93 G4UPolyhedra::~G4UPolyhedra() >> 94 { >> 95 } 145 96 146 97 147 ////////////////////////////////////////////// 98 //////////////////////////////////////////////////////////////////////// 148 // 99 // 149 // Copy constructor 100 // Copy constructor 150 // 101 // 151 G4UPolyhedra::G4UPolyhedra( const G4UPolyhedra << 102 G4UPolyhedra::G4UPolyhedra( const G4UPolyhedra &source ) 152 : Base_t( source ) << 103 : G4USolid( source ) 153 { 104 { 154 fGenericPgon = source.fGenericPgon; << 155 fOriginalParameters = source.fOriginalParame << 156 wrStart = source.wrStart; << 157 wrDelta = source.wrDelta; << 158 wrNumSide = source.wrNumSide; << 159 rzcorners = source.rzcorners; << 160 } 105 } 161 106 162 107 163 ////////////////////////////////////////////// 108 //////////////////////////////////////////////////////////////////////// 164 // 109 // 165 // Assignment operator 110 // Assignment operator 166 // 111 // 167 G4UPolyhedra& G4UPolyhedra::operator=( const G << 112 G4UPolyhedra& G4UPolyhedra::operator=( const G4UPolyhedra &source ) 168 { 113 { 169 if (this == &source) return *this; 114 if (this == &source) return *this; 170 115 171 Base_t::operator=( source ); << 116 G4USolid::operator=( source ); 172 fGenericPgon = source.fGenericPgon; << 117 173 fOriginalParameters = source.fOriginalParame << 174 wrStart = source.wrStart; << 175 wrDelta = source.wrDelta; << 176 wrNumSide = source.wrNumSide; << 177 rzcorners = source.rzcorners; << 178 << 179 return *this; 118 return *this; 180 } 119 } 181 120 182 121 183 ////////////////////////////////////////////// 122 //////////////////////////////////////////////////////////////////////// 184 // 123 // 185 // Accessors & modifiers 124 // Accessors & modifiers 186 // 125 // 187 G4int G4UPolyhedra::GetNumSide() const 126 G4int G4UPolyhedra::GetNumSide() const 188 { 127 { 189 return wrNumSide; << 128 return GetShape()->GetNumSide(); 190 } 129 } 191 G4double G4UPolyhedra::GetStartPhi() const 130 G4double G4UPolyhedra::GetStartPhi() const 192 { 131 { 193 return wrStart; << 132 return GetShape()->GetStartPhi(); 194 } 133 } 195 G4double G4UPolyhedra::GetEndPhi() const 134 G4double G4UPolyhedra::GetEndPhi() const 196 { 135 { 197 return (wrStart + wrDelta); << 136 return GetShape()->GetEndPhi(); 198 } << 199 G4double G4UPolyhedra::GetSinStartPhi() const << 200 { << 201 G4double phi = GetStartPhi(); << 202 return std::sin(phi); << 203 } << 204 G4double G4UPolyhedra::GetCosStartPhi() const << 205 { << 206 G4double phi = GetStartPhi(); << 207 return std::cos(phi); << 208 } << 209 G4double G4UPolyhedra::GetSinEndPhi() const << 210 { << 211 G4double phi = GetEndPhi(); << 212 return std::sin(phi); << 213 } << 214 G4double G4UPolyhedra::GetCosEndPhi() const << 215 { << 216 G4double phi = GetEndPhi(); << 217 return std::cos(phi); << 218 } 137 } 219 G4bool G4UPolyhedra::IsOpen() const 138 G4bool G4UPolyhedra::IsOpen() const 220 { 139 { 221 return (wrDelta < twopi); << 140 return GetShape()->IsOpen(); 222 } 141 } 223 G4bool G4UPolyhedra::IsGeneric() const 142 G4bool G4UPolyhedra::IsGeneric() const 224 { 143 { 225 return fGenericPgon; << 144 return GetShape()->IsGeneric(); 226 } 145 } 227 G4int G4UPolyhedra::GetNumRZCorner() const 146 G4int G4UPolyhedra::GetNumRZCorner() const 228 { 147 { 229 return rzcorners.size(); << 148 return GetShape()->GetNumRZCorner(); 230 } 149 } 231 G4PolyhedraSideRZ G4UPolyhedra::GetCorner(G4in 150 G4PolyhedraSideRZ G4UPolyhedra::GetCorner(G4int index) const 232 { 151 { 233 G4TwoVector rz = rzcorners.at(index); << 152 UPolyhedraSideRZ pside = GetShape()->GetCorner(index); 234 G4PolyhedraSideRZ psiderz = { rz.x(), rz.y() << 153 G4PolyhedraSideRZ psiderz = { pside.r, pside.z }; 235 154 236 return psiderz; 155 return psiderz; 237 } 156 } 238 G4PolyhedraHistorical* G4UPolyhedra::GetOrigin 157 G4PolyhedraHistorical* G4UPolyhedra::GetOriginalParameters() const 239 { 158 { 240 return new G4PolyhedraHistorical(fOriginalPa << 159 UPolyhedraHistorical* pars = GetShape()->GetOriginalParameters(); 241 } << 160 G4PolyhedraHistorical* pdata = new G4PolyhedraHistorical(pars->fNumZPlanes); 242 void G4UPolyhedra::SetOriginalParameters() << 161 pdata->Start_angle = pars->fStartAngle; 243 { << 162 pdata->Opening_angle = pars->fOpeningAngle; 244 G4double startPhi = GetPhiStart(); << 163 pdata->numSide = pars->fNumSide; 245 G4double deltaPhi = GetPhiDelta(); << 164 for (G4int i=0; i<pars->fNumZPlanes; ++i) 246 G4int numPlanes = GetZSegmentCount() + 1; << 165 { 247 G4int numSides = GetSideCount(); << 166 pdata->Z_values[i] = pars->fZValues[i]; 248 << 167 pdata->Rmin[i] = pars->Rmin[i]; 249 fOriginalParameters.Start_angle = startPhi << 168 pdata->Rmax[i] = pars->Rmax[i]; 250 fOriginalParameters.Opening_angle = deltaPhi << 251 fOriginalParameters.Num_z_planes = numPlane << 252 fOriginalParameters.numSide = numSides << 253 << 254 delete [] fOriginalParameters.Z_values; << 255 delete [] fOriginalParameters.Rmin; << 256 delete [] fOriginalParameters.Rmax; << 257 fOriginalParameters.Z_values = new G4double[ << 258 fOriginalParameters.Rmin = new G4double[numP << 259 fOriginalParameters.Rmax = new G4double[numP << 260 << 261 G4double convertRad = fGenericPgon << 262 ? 1.0 : std::cos(0.5*del << 263 for (G4int i=0; i<numPlanes; ++i) << 264 { << 265 fOriginalParameters.Z_values[i] = GetZPlan << 266 fOriginalParameters.Rmax[i] = GetRMax( << 267 fOriginalParameters.Rmin[i] = GetRMin( << 268 } 169 } >> 170 return pdata; 269 } 171 } 270 void G4UPolyhedra::SetOriginalParameters(G4Pol 172 void G4UPolyhedra::SetOriginalParameters(G4PolyhedraHistorical* pars) 271 { 173 { 272 fOriginalParameters = *pars; << 174 UPolyhedraHistorical* pdata = GetShape()->GetOriginalParameters(); >> 175 pdata->fStartAngle = pars->Start_angle; >> 176 pdata->fOpeningAngle = pars->Opening_angle; >> 177 pdata->fNumSide = pars->numSide; >> 178 pdata->fNumZPlanes = pars->Num_z_planes; >> 179 for (G4int i=0; i<pdata->fNumZPlanes; ++i) >> 180 { >> 181 pdata->fZValues[i] = pars->Z_values[i]; >> 182 pdata->Rmin[i] = pars->Rmin[i]; >> 183 pdata->Rmax[i] = pars->Rmax[i]; >> 184 } 273 fRebuildPolyhedron = true; 185 fRebuildPolyhedron = true; 274 Reset(); << 275 } 186 } 276 << 277 G4bool G4UPolyhedra::Reset() 187 G4bool G4UPolyhedra::Reset() 278 { 188 { 279 if (fGenericPgon) << 189 return GetShape()->Reset(); 280 { << 281 std::ostringstream message; << 282 message << "Solid " << GetName() << " buil << 283 << G4endl << "Not applicable to th << 284 G4Exception("G4UPolyhedra::Reset()", "Geom << 285 JustWarning, message, "Paramet << 286 return true; // error code set << 287 } << 288 << 289 // << 290 // Rebuild polyhedra based on original param << 291 // << 292 wrStart = fOriginalParameters.Start_angle; << 293 while (wrStart < 0.) << 294 { << 295 wrStart += twopi; << 296 } << 297 wrDelta = fOriginalParameters.Opening_angle; << 298 if (wrDelta <= 0. || wrDelta >= twopi*(1-DBL << 299 { << 300 wrDelta = twopi; << 301 } << 302 wrNumSide = fOriginalParameters.numSide; << 303 rzcorners.resize(0); << 304 for (G4int i=0; i<fOriginalParameters.Num_z_ << 305 { << 306 G4double z = fOriginalParameters.Z_values[ << 307 G4double r = fOriginalParameters.Rmax[i]; << 308 rzcorners.emplace_back(r,z); << 309 } << 310 for (G4int i=fOriginalParameters.Num_z_plane << 311 { << 312 G4double z = fOriginalParameters.Z_values[ << 313 G4double r = fOriginalParameters.Rmin[i]; << 314 rzcorners.emplace_back(r,z); << 315 } << 316 std::vector<G4int> iout; << 317 G4GeomTools::RemoveRedundantVertices(rzcorne << 318 << 319 return false; // error code unset << 320 } 190 } 321 191 322 192 323 ////////////////////////////////////////////// 193 //////////////////////////////////////////////////////////////////////// 324 // 194 // 325 // Dispatch to parameterisation for replicatio 195 // Dispatch to parameterisation for replication mechanism dimension 326 // computation & modification. 196 // computation & modification. 327 // 197 // 328 void G4UPolyhedra::ComputeDimensions(G4VPVPara 198 void G4UPolyhedra::ComputeDimensions(G4VPVParameterisation* p, 329 const G4i 199 const G4int n, 330 const G4V 200 const G4VPhysicalVolume* pRep) 331 { 201 { 332 p->ComputeDimensions(*(G4Polyhedra*)this,n,p 202 p->ComputeDimensions(*(G4Polyhedra*)this,n,pRep); 333 } 203 } 334 204 335 205 336 ////////////////////////////////////////////// 206 ////////////////////////////////////////////////////////////////////////// 337 // 207 // 338 // Make a clone of the object 208 // Make a clone of the object 339 209 340 G4VSolid* G4UPolyhedra::Clone() const 210 G4VSolid* G4UPolyhedra::Clone() const 341 { 211 { 342 return new G4UPolyhedra(*this); 212 return new G4UPolyhedra(*this); 343 } 213 } 344 214 345 215 346 ////////////////////////////////////////////// << 216 //////////////////////////////////////////////////////////////////////// 347 // 217 // 348 // Get bounding box << 218 // CreatePolyhedron 349 << 219 // 350 void G4UPolyhedra::BoundingLimits(G4ThreeVecto << 220 G4Polyhedron* G4UPolyhedra::CreatePolyhedron() const 351 G4ThreeVecto << 352 { 221 { 353 static G4bool checkBBox = true; << 222 if (!IsGeneric()) 354 static G4bool checkPhi = true; << 355 << 356 G4double rmin = kInfinity, rmax = -kInfinity << 357 G4double zmin = kInfinity, zmax = -kInfinity << 358 for (G4int i=0; i<GetNumRZCorner(); ++i) << 359 { << 360 G4PolyhedraSideRZ corner = GetCorner(i); << 361 if (corner.r < rmin) rmin = corner.r; << 362 if (corner.r > rmax) rmax = corner.r; << 363 if (corner.z < zmin) zmin = corner.z; << 364 if (corner.z > zmax) zmax = corner.z; << 365 } << 366 << 367 G4double sphi = GetStartPhi(); << 368 G4double ephi = GetEndPhi(); << 369 G4double dphi = IsOpen() ? ephi-sphi : tw << 370 G4int ksteps = GetNumSide(); << 371 G4double astep = dphi/ksteps; << 372 G4double sinStep = std::sin(astep); << 373 G4double cosStep = std::cos(astep); << 374 << 375 G4double sinCur = GetSinStartPhi(); << 376 G4double cosCur = GetCosStartPhi(); << 377 if (!IsOpen()) rmin = 0.; << 378 G4double xmin = rmin*cosCur, xmax = xmin; << 379 G4double ymin = rmin*sinCur, ymax = ymin; << 380 for (G4int k=0; k<ksteps+1; ++k) << 381 { 223 { 382 G4double x = rmax*cosCur; << 224 G4PolyhedraHistorical* original_parameters = GetOriginalParameters(); 383 if (x < xmin) xmin = x; << 225 G4PolyhedronPgon* 384 if (x > xmax) xmax = x; << 226 polyhedron = new G4PolyhedronPgon( GetOriginalParameters()->Start_angle, 385 G4double y = rmax*sinCur; << 227 GetOriginalParameters()->Opening_angle, 386 if (y < ymin) ymin = y; << 228 GetOriginalParameters()->numSide, 387 if (y > ymax) ymax = y; << 229 GetOriginalParameters()->Num_z_planes, 388 if (rmin > 0.) << 230 GetOriginalParameters()->Z_values, >> 231 GetOriginalParameters()->Rmin, >> 232 GetOriginalParameters()->Rmax); >> 233 delete original_parameters; // delete local copy >> 234 return polyhedron; >> 235 } >> 236 else >> 237 { >> 238 // The following code prepares for: >> 239 // HepPolyhedron::createPolyhedron(int Nnodes, int Nfaces, >> 240 // const double xyz[][3], >> 241 // const int faces_vec[][4]) >> 242 // Here is an extract from the header file HepPolyhedron.h: >> 243 /** >> 244 * Creates user defined polyhedron. >> 245 * This function allows to the user to define arbitrary polyhedron. >> 246 * The faces of the polyhedron should be either triangles or planar >> 247 * quadrilateral. Nodes of a face are defined by indexes pointing to >> 248 * the elements in the xyz array. Numeration of the elements in the >> 249 * array starts from 1 (like in fortran). The indexes can be positive >> 250 * or negative. Negative sign means that the corresponding edge is >> 251 * invisible. The normal of the face should be directed to exterior >> 252 * of the polyhedron. >> 253 * >> 254 * @param Nnodes number of nodes >> 255 * @param Nfaces number of faces >> 256 * @param xyz nodes >> 257 * @param faces_vec faces (quadrilaterals or triangles) >> 258 * @return status of the operation - is non-zero in case of problem >> 259 */ >> 260 G4int nNodes; >> 261 G4int nFaces; >> 262 typedef G4double double3[3]; >> 263 double3* xyz; >> 264 typedef G4int int4[4]; >> 265 int4* faces_vec; >> 266 if (IsOpen()) 389 { 267 { 390 G4double xx = rmin*cosCur; << 268 // Triangulate open ends. Simple ear-chopping algorithm... 391 if (xx < xmin) xmin = xx; << 269 // I'm not sure how robust this algorithm is (J.Allison). 392 if (xx > xmax) xmax = xx; << 270 // 393 G4double yy = rmin*sinCur; << 271 std::vector<G4bool> chopped(GetNumRZCorner(), false); 394 if (yy < ymin) ymin = yy; << 272 std::vector<G4int*> triQuads; 395 if (yy > ymax) ymax = yy; << 273 G4int remaining = GetNumRZCorner(); >> 274 G4int iStarter = 0; >> 275 while (remaining >= 3) // Loop checking, 13.08.2015, G.Cosmo >> 276 { >> 277 // Find unchopped corners... >> 278 // >> 279 G4int A = -1, B = -1, C = -1; >> 280 G4int iStepper = iStarter; >> 281 do // Loop checking, 13.08.2015, G.Cosmo >> 282 { >> 283 if (A < 0) { A = iStepper; } >> 284 else if (B < 0) { B = iStepper; } >> 285 else if (C < 0) { C = iStepper; } >> 286 do // Loop checking, 13.08.2015, G.Cosmo >> 287 { >> 288 if (++iStepper >= GetNumRZCorner()) iStepper = 0; >> 289 } >> 290 while (chopped[iStepper]); >> 291 } >> 292 while (C < 0 && iStepper != iStarter); >> 293 >> 294 // Check triangle at B is pointing outward (an "ear"). >> 295 // Sign of z cross product determines... >> 296 >> 297 G4double BAr = GetCorner(A).r - GetCorner(B).r; >> 298 G4double BAz = GetCorner(A).z - GetCorner(B).z; >> 299 G4double BCr = GetCorner(C).r - GetCorner(B).r; >> 300 G4double BCz = GetCorner(C).z - GetCorner(B).z; >> 301 if (BAr * BCz - BAz * BCr < kCarTolerance) >> 302 { >> 303 G4int* tq = new G4int[3]; >> 304 tq[0] = A + 1; >> 305 tq[1] = B + 1; >> 306 tq[2] = C + 1; >> 307 triQuads.push_back(tq); >> 308 chopped[B] = true; >> 309 --remaining; >> 310 } >> 311 else >> 312 { >> 313 do // Loop checking, 13.08.2015, G.Cosmo >> 314 { >> 315 if (++iStarter >= GetNumRZCorner()) { iStarter = 0; } >> 316 } >> 317 while (chopped[iStarter]); >> 318 } >> 319 } >> 320 >> 321 // Transfer to faces... >> 322 G4int numSide=GetNumSide(); >> 323 nNodes = (numSide + 1) * GetNumRZCorner(); >> 324 nFaces = numSide * GetNumRZCorner() + 2 * triQuads.size(); >> 325 faces_vec = new int4[nFaces]; >> 326 G4int iface = 0; >> 327 G4int addition = GetNumRZCorner() * numSide; >> 328 G4int d = GetNumRZCorner() - 1; >> 329 for (G4int iEnd = 0; iEnd < 2; ++iEnd) >> 330 { >> 331 for (size_t i = 0; i < triQuads.size(); ++i) >> 332 { >> 333 // Negative for soft/auxiliary/normally invisible edges... >> 334 // >> 335 G4int a, b, c; >> 336 if (iEnd == 0) >> 337 { >> 338 a = triQuads[i][0]; >> 339 b = triQuads[i][1]; >> 340 c = triQuads[i][2]; >> 341 } >> 342 else >> 343 { >> 344 a = triQuads[i][0] + addition; >> 345 b = triQuads[i][2] + addition; >> 346 c = triQuads[i][1] + addition; >> 347 } >> 348 G4int ab = std::abs(b - a); >> 349 G4int bc = std::abs(c - b); >> 350 G4int ca = std::abs(a - c); >> 351 faces_vec[iface][0] = (ab == 1 || ab == d)? a: -a; >> 352 faces_vec[iface][1] = (bc == 1 || bc == d)? b: -b; >> 353 faces_vec[iface][2] = (ca == 1 || ca == d)? c: -c; >> 354 faces_vec[iface][3] = 0; >> 355 ++iface; >> 356 } >> 357 } >> 358 >> 359 // Continue with sides... >> 360 >> 361 xyz = new double3[nNodes]; >> 362 const G4double dPhi = (GetEndPhi() - GetStartPhi()) / numSide; >> 363 G4double phi = GetStartPhi(); >> 364 G4int ixyz = 0; >> 365 for (G4int iSide = 0; iSide < numSide; ++iSide) >> 366 { >> 367 for (G4int iCorner = 0; iCorner < GetNumRZCorner(); ++iCorner) >> 368 { >> 369 xyz[ixyz][0] = GetCorner(iCorner).r * std::cos(phi); >> 370 xyz[ixyz][1] = GetCorner(iCorner).r * std::sin(phi); >> 371 xyz[ixyz][2] = GetCorner(iCorner).z; >> 372 if (iCorner < GetNumRZCorner() - 1) >> 373 { >> 374 faces_vec[iface][0] = ixyz + 1; >> 375 faces_vec[iface][1] = ixyz + GetNumRZCorner() + 1; >> 376 faces_vec[iface][2] = ixyz + GetNumRZCorner() + 2; >> 377 faces_vec[iface][3] = ixyz + 2; >> 378 } >> 379 else >> 380 { >> 381 faces_vec[iface][0] = ixyz + 1; >> 382 faces_vec[iface][1] = ixyz + GetNumRZCorner() + 1; >> 383 faces_vec[iface][2] = ixyz + 2; >> 384 faces_vec[iface][3] = ixyz - GetNumRZCorner() + 2; >> 385 } >> 386 ++iface; >> 387 ++ixyz; >> 388 } >> 389 phi += dPhi; >> 390 } >> 391 >> 392 // Last GetCorner... >> 393 >> 394 for (G4int iCorner = 0; iCorner < GetNumRZCorner(); ++iCorner) >> 395 { >> 396 xyz[ixyz][0] = GetCorner(iCorner).r * std::cos(phi); >> 397 xyz[ixyz][1] = GetCorner(iCorner).r * std::sin(phi); >> 398 xyz[ixyz][2] = GetCorner(iCorner).z; >> 399 ++ixyz; >> 400 } 396 } 401 } 397 G4double sinTmp = sinCur; << 402 else // !phiIsOpen - i.e., a complete 360 degrees. 398 sinCur = sinCur*cosStep + cosCur*sinStep; << 399 cosCur = cosCur*cosStep - sinTmp*sinStep; << 400 } << 401 pMin.set(xmin,ymin,zmin); << 402 pMax.set(xmax,ymax,zmax); << 403 << 404 // Check correctness of the bounding box << 405 // << 406 if (pMin.x() >= pMax.x() || pMin.y() >= pMax << 407 { << 408 std::ostringstream message; << 409 message << "Bad bounding box (min >= max) << 410 << GetName() << " !" << 411 << "\npMin = " << pMin << 412 << "\npMax = " << pMax; << 413 G4Exception("G4UPolyhedra::BoundingLimits( << 414 JustWarning, message); << 415 StreamInfo(G4cout); << 416 } << 417 << 418 // Check consistency of bounding boxes << 419 // << 420 if (checkBBox) << 421 { << 422 U3Vector vmin, vmax; << 423 Extent(vmin,vmax); << 424 if (std::abs(pMin.x()-vmin.x()) > kCarTole << 425 std::abs(pMin.y()-vmin.y()) > kCarTole << 426 std::abs(pMin.z()-vmin.z()) > kCarTole << 427 std::abs(pMax.x()-vmax.x()) > kCarTole << 428 std::abs(pMax.y()-vmax.y()) > kCarTole << 429 std::abs(pMax.z()-vmax.z()) > kCarTole << 430 { 403 { 431 std::ostringstream message; << 404 nNodes = GetNumSide() * GetNumRZCorner(); 432 message << "Inconsistency in bounding bo << 405 nFaces = GetNumSide() * GetNumRZCorner();; 433 << GetName() << " !" << 406 xyz = new double3[nNodes]; 434 << "\nBBox min: wrapper = " << p << 407 faces_vec = new int4[nFaces]; 435 << "\nBBox max: wrapper = " << p << 408 // const G4double dPhi = (endPhi - startPhi) / numSide; 436 G4Exception("G4UPolyhedra::BoundingLimit << 409 const G4double dPhi = twopi / GetNumSide(); // !phiIsOpen endPhi-startPhi = 360 degrees. 437 JustWarning, message); << 410 G4double phi = GetStartPhi(); 438 checkBBox = false; << 411 G4int ixyz = 0, iface = 0; >> 412 for (G4int iSide = 0; iSide < GetNumSide(); ++iSide) >> 413 { >> 414 for (G4int iCorner = 0; iCorner < GetNumRZCorner(); ++iCorner) >> 415 { >> 416 xyz[ixyz][0] = GetCorner(iCorner).r * std::cos(phi); >> 417 xyz[ixyz][1] = GetCorner(iCorner).r * std::sin(phi); >> 418 xyz[ixyz][2] = GetCorner(iCorner).z; >> 419 if (iSide < GetNumSide() - 1) >> 420 { >> 421 if (iCorner < GetNumRZCorner() - 1) >> 422 { >> 423 faces_vec[iface][0] = ixyz + 1; >> 424 faces_vec[iface][1] = ixyz + GetNumRZCorner() + 1; >> 425 faces_vec[iface][2] = ixyz + GetNumRZCorner() + 2; >> 426 faces_vec[iface][3] = ixyz + 2; >> 427 } >> 428 else >> 429 { >> 430 faces_vec[iface][0] = ixyz + 1; >> 431 faces_vec[iface][1] = ixyz + GetNumRZCorner() + 1; >> 432 faces_vec[iface][2] = ixyz + 2; >> 433 faces_vec[iface][3] = ixyz - GetNumRZCorner() + 2; >> 434 } >> 435 } >> 436 else // Last side joins ends... >> 437 { >> 438 if (iCorner < GetNumRZCorner() - 1) >> 439 { >> 440 faces_vec[iface][0] = ixyz + 1; >> 441 faces_vec[iface][1] = ixyz + GetNumRZCorner() - nFaces + 1; >> 442 faces_vec[iface][2] = ixyz + GetNumRZCorner() - nFaces + 2; >> 443 faces_vec[iface][3] = ixyz + 2; >> 444 } >> 445 else >> 446 { >> 447 faces_vec[iface][0] = ixyz + 1; >> 448 faces_vec[iface][1] = ixyz - nFaces + GetNumRZCorner() + 1; >> 449 faces_vec[iface][2] = ixyz - nFaces + 2; >> 450 faces_vec[iface][3] = ixyz - GetNumRZCorner() + 2; >> 451 } >> 452 } >> 453 ++ixyz; >> 454 ++iface; >> 455 } >> 456 phi += dPhi; >> 457 } 439 } 458 } 440 } << 459 G4Polyhedron* polyhedron = new G4Polyhedron; 441 << 460 G4int problem = polyhedron->createPolyhedron(nNodes, nFaces, xyz, faces_vec); 442 // Check consistency of angles << 461 delete [] faces_vec; 443 // << 462 delete [] xyz; 444 if (checkPhi) << 463 if (problem) 445 { << 446 if (GetStartPhi() != GetPhiStart() || << 447 GetEndPhi() != GetPhiEnd() || << 448 GetNumSide() != GetSideCount() || << 449 IsOpen() != (Base_t::GetPhiDelta( << 450 { 464 { 451 std::ostringstream message; 465 std::ostringstream message; 452 message << "Inconsistency in Phi angles << 466 message << "Problem creating G4Polyhedron for: " << GetName(); 453 << GetName() << " !" << 467 G4Exception("G4Polyhedra::CreatePolyhedron()", "GeomSolids1002", 454 << "\nPhi start : wrapper = " < << 455 << " solid = " << GetPhiStar << 456 << "\nPhi end : wrapper = " < << 457 << " solid = " << GetPhiEnd( << 458 << "\nPhi # sides: wrapper = " < << 459 << " solid = " << GetSideCou << 460 << "\nPhi is open: wrapper = " < << 461 << " solid = " << 462 << ((Base_t::GetPhiDelta() < two << 463 G4Exception("G4UPolyhedra::BoundingLimit << 464 JustWarning, message); 468 JustWarning, message); 465 checkPhi = false; << 469 delete polyhedron; >> 470 return 0; 466 } 471 } 467 } << 472 else 468 } << 469 << 470 ////////////////////////////////////////////// << 471 // << 472 // Calculate extent under transform and specif << 473 << 474 G4bool << 475 G4UPolyhedra::CalculateExtent(const EAxis pAxi << 476 const G4VoxelLim << 477 const G4AffineTr << 478 G4double& << 479 { << 480 G4ThreeVector bmin, bmax; << 481 G4bool exist; << 482 << 483 // Check bounding box (bbox) << 484 // << 485 BoundingLimits(bmin,bmax); << 486 G4BoundingEnvelope bbox(bmin,bmax); << 487 #ifdef G4BBOX_EXTENT << 488 if (true) return bbox.CalculateExtent(pAxis, << 489 #endif << 490 if (bbox.BoundingBoxVsVoxelLimits(pAxis,pVox << 491 { << 492 return exist = pMin < pMax; << 493 } << 494 << 495 // To find the extent, RZ contour of the pol << 496 // in triangles. The extent is calculated as << 497 // all sub-polycones formed by rotation of t << 498 // << 499 G4TwoVectorList contourRZ; << 500 G4TwoVectorList triangles; << 501 std::vector<G4int> iout; << 502 G4double eminlim = pVoxelLimit.GetMinExtent( << 503 G4double emaxlim = pVoxelLimit.GetMaxExtent( << 504 << 505 // get RZ contour, ensure anticlockwise orde << 506 for (G4int i=0; i<GetNumRZCorner(); ++i) << 507 { << 508 G4PolyhedraSideRZ corner = GetCorner(i); << 509 contourRZ.emplace_back(corner.r,corner.z); << 510 } << 511 G4GeomTools::RemoveRedundantVertices(contour << 512 G4double area = G4GeomTools::PolygonArea(con << 513 if (area < 0.) std::reverse(contourRZ.begin( << 514 << 515 // triangulate RZ countour << 516 if (!G4GeomTools::TriangulatePolygon(contour << 517 { << 518 std::ostringstream message; << 519 message << "Triangulation of RZ contour ha << 520 << GetName() << " !" << 521 << "\nExtent has been calculated u << 522 G4Exception("G4UPolyhedra::CalculateExtent << 523 "GeomMgt1002",JustWarning,mess << 524 return bbox.CalculateExtent(pAxis,pVoxelLi << 525 } << 526 << 527 // set trigonometric values << 528 G4double sphi = GetStartPhi(); << 529 G4double ephi = GetEndPhi(); << 530 G4double dphi = IsOpen() ? ephi-sphi : t << 531 G4int ksteps = GetNumSide(); << 532 G4double astep = dphi/ksteps; << 533 G4double sinStep = std::sin(astep); << 534 G4double cosStep = std::cos(astep); << 535 G4double sinStart = GetSinStartPhi(); << 536 G4double cosStart = GetCosStartPhi(); << 537 << 538 // allocate vector lists << 539 std::vector<const G4ThreeVectorList *> polyg << 540 polygons.resize(ksteps+1); << 541 for (G4int k=0; k<ksteps+1; ++k) << 542 { << 543 polygons[k] = new G4ThreeVectorList(3); << 544 } << 545 << 546 // main loop along triangles << 547 pMin = kInfinity; << 548 pMax = -kInfinity; << 549 G4int ntria = triangles.size()/3; << 550 for (G4int i=0; i<ntria; ++i) << 551 { << 552 G4double sinCur = sinStart; << 553 G4double cosCur = cosStart; << 554 G4int i3 = i*3; << 555 for (G4int k=0; k<ksteps+1; ++k) // rotate << 556 { 473 { 557 auto ptr = const_cast<G4ThreeVectorList* << 474 return polyhedron; 558 auto iter = ptr->begin(); << 559 iter->set(triangles[i3+0].x()*cosCur, << 560 triangles[i3+0].x()*sinCur, << 561 triangles[i3+0].y()); << 562 iter++; << 563 iter->set(triangles[i3+1].x()*cosCur, << 564 triangles[i3+1].x()*sinCur, << 565 triangles[i3+1].y()); << 566 iter++; << 567 iter->set(triangles[i3+2].x()*cosCur, << 568 triangles[i3+2].x()*sinCur, << 569 triangles[i3+2].y()); << 570 << 571 G4double sinTmp = sinCur; << 572 sinCur = sinCur*cosStep + cosCur*sinStep << 573 cosCur = cosCur*cosStep - sinTmp*sinStep << 574 } 475 } 575 << 576 // set sub-envelope and adjust extent << 577 G4double emin,emax; << 578 G4BoundingEnvelope benv(polygons); << 579 if (!benv.CalculateExtent(pAxis,pVoxelLimi << 580 if (emin < pMin) pMin = emin; << 581 if (emax > pMax) pMax = emax; << 582 if (eminlim > pMin && emaxlim < pMax) brea << 583 } 476 } 584 // free memory << 585 for (G4int k=0; k<ksteps+1; ++k) { delete po << 586 return (pMin < pMax); << 587 } << 588 << 589 << 590 ////////////////////////////////////////////// << 591 // << 592 // CreatePolyhedron << 593 // << 594 G4Polyhedron* G4UPolyhedra::CreatePolyhedron() << 595 { << 596 return new G4PolyhedronPgon(wrStart, wrDelta << 597 } 477 } 598 478 599 #endif // G4GEOM_USE_USOLIDS 479 #endif // G4GEOM_USE_USOLIDS 600 480