154 G4VSolid* theSolid(
nullptr);
158 if(sharedShapes.find(geoShape)!=sharedShapes.end())
159 return sharedShapes[geoShape];
162 G4VSolid* solidA(
nullptr);
163 G4VSolid* solidB(
nullptr);
169 if(geoShape->typeID() == GeoBox::getClassTypeID() )
171 const GeoBox* theBox =
dynamic_cast<const GeoBox*
> (geoShape);
172 if (
nullptr==theBox)
throw std::runtime_error(
"TypeID did not match cast for box");
173 if (
n.empty())
n=
"G4Box";
174 if (theBox->getXHalfLength()<=0.){
ATH_MSG_WARNING(
"Box " <<
n <<
" has an x side of " << theBox->getXHalfLength() <<
" - using std::abs.");}
175 if (theBox->getYHalfLength()<=0.){
ATH_MSG_WARNING(
"Box " <<
n <<
" has an y side of " << theBox->getYHalfLength() <<
" - using std::abs.");}
176 if (theBox->getZHalfLength()<=0.){
ATH_MSG_WARNING(
"Box " <<
n <<
" has an z side of " << theBox->getZHalfLength() <<
" - using std::abs.");}
177 theSolid =
new G4Box(
n,
178 std::abs(theBox->getXHalfLength()),
179 std::abs(theBox->getYHalfLength()),
180 std::abs(theBox->getZHalfLength()));
185 else if(geoShape->typeID() == GeoTube::getClassTypeID() )
187 const GeoTube* theTube =
dynamic_cast<const GeoTube*
> (geoShape);
188 if (
nullptr==theTube)
throw std::runtime_error(
"TypeID did not match cast for tube");
189 if (
n.empty())
n=
"G4Tube";
190 if (theTube->getRMax()<=0.){
ATH_MSG_WARNING(
"Tube " <<
n <<
" has a max radius of " << theTube->getRMax() <<
" - using std::abs.");}
191 if (theTube->getZHalfLength()<=0.){
ATH_MSG_WARNING(
"Tube " <<
n <<
" has a z half length of " << theTube->getZHalfLength() <<
" - using std::abs.");}
192 if (theTube->getRMax()<theTube->getRMin()){
ATH_MSG_WARNING(
"Tube " <<
n <<
" has a max radius of " << theTube->getRMax() <<
" and a min radius of " << theTube->getRMin());}
193 theSolid =
new G4Tubs(
n,
195 std::abs(theTube->getRMax()),
196 std::abs(theTube->getZHalfLength()),
202 else if(geoShape->typeID() == GeoTubs::getClassTypeID() )
204 const GeoTubs* theTubs =
dynamic_cast<const GeoTubs*
> (geoShape);
205 if (
nullptr==theTubs)
throw std::runtime_error(
"TypeID did not match cast for tubs");
206 if (
n.empty())
n=
"G4Tubs";
207 if (theTubs->getRMin()<0.){
ATH_MSG_WARNING(
"Tubs " <<
n <<
" has a min radius of " << theTubs->getRMax());}
208 if (theTubs->getRMax()<=0.){
ATH_MSG_WARNING(
"Tubs " <<
n <<
" has a max radius of " << theTubs->getRMax() <<
" - using std::abs.");}
209 if (theTubs->getZHalfLength()<=0.){
ATH_MSG_WARNING(
"Tubs " <<
n <<
" has a half length of " << theTubs->getZHalfLength() <<
" - using std::abs.");}
210 if (theTubs->getRMax()<theTubs->getRMin()){
ATH_MSG_WARNING(
"Tubs " <<
n <<
" has a max radius of " << theTubs->getRMax() <<
" and a min radius of " << theTubs->getRMin());}
211 if (theTubs->getDPhi()<=0.){
ATH_MSG_WARNING(
"Tubs " <<
n <<
" has a dPhi of " << theTubs->getDPhi());}
212 theSolid =
new G4Tubs(
n,
214 std::abs(theTubs->getRMax()),
215 std::abs(theTubs->getZHalfLength()),
222 else if(geoShape->typeID() == GeoTrd::getClassTypeID() )
224 const GeoTrd* theTrd =
dynamic_cast<const GeoTrd*
> (geoShape);
225 if (
nullptr==theTrd)
throw std::runtime_error(
"TypeID did not match cast for trd");
226 if (
n.empty())
n=
"G4Trd";
227 if (theTrd->getXHalfLength1()<0.){
ATH_MSG_WARNING(
"Trd " <<
n <<
" has a x half length 1 of " << theTrd->getXHalfLength1() <<
" - using std::abs.");}
228 if (theTrd->getXHalfLength2()<0.){
ATH_MSG_WARNING(
"Trd " <<
n <<
" has a x half length 2 of " << theTrd->getXHalfLength2() <<
" - using std::abs.");}
229 if (theTrd->getYHalfLength1()<0.){
ATH_MSG_WARNING(
"Trd " <<
n <<
" has a y half length 1 of " << theTrd->getYHalfLength1() <<
" - using std::abs.");}
230 if (theTrd->getYHalfLength2()<0.){
ATH_MSG_WARNING(
"Trd " <<
n <<
" has a y half length 2 of " << theTrd->getYHalfLength2() <<
" - using std::abs.");}
231 if (theTrd->getZHalfLength()<=0.){
ATH_MSG_WARNING(
"Trd " <<
n <<
" has a z half length of " << theTrd->getZHalfLength() <<
" - using std::abs.");}
232 if (theTrd->getXHalfLength1()<=0. && theTrd->getXHalfLength2()<=0.){
ATH_MSG_WARNING(
"Trd " <<
n <<
" has an x half length 1 of " << theTrd->getXHalfLength1()
233 <<
" and an x half length 2 of " << theTrd->getXHalfLength2() <<
" - using std::abs.");}
234 if (theTrd->getYHalfLength1()<=0. && theTrd->getYHalfLength2()<=0.){
ATH_MSG_WARNING(
"Trd " <<
n <<
" has a y half length 1 of " << theTrd->getYHalfLength1()
235 <<
" and a y half length 2 of " << theTrd->getYHalfLength2() <<
" - using std::abs.");}
236 theSolid =
new G4Trd(
n,
237 std::abs(theTrd->getXHalfLength1()),
238 std::abs(theTrd->getXHalfLength2()),
239 std::abs(theTrd->getYHalfLength1()),
240 std::abs(theTrd->getYHalfLength2()),
241 std::abs(theTrd->getZHalfLength()));
246 else if(geoShape->typeID() == GeoPcon::getClassTypeID())
248 const GeoPcon* thePcon =
dynamic_cast<const GeoPcon*
>(geoShape);
249 if (
nullptr==thePcon)
throw std::runtime_error(
"TypeID did not match cast for pcon");
250 theSolid =
new G4Polycone(
n.empty()?
"G4Polycone":std::move(
n),
253 thePcon->getNPlanes(),
254 thePcon->getZPlaneBuff(),
255 thePcon->getRMinBuff(),
256 thePcon->getRMaxBuff());
261 else if(geoShape->typeID() == GeoCons::getClassTypeID())
263 const GeoCons* theCons =
dynamic_cast<const GeoCons*
>(geoShape);
264 if (
nullptr==theCons)
throw std::runtime_error(
"TypeID did not match cast for cons");
265 if (
n.empty())
n=
"G4Cons";
266 if (theCons->getRMax1()<0.){
ATH_MSG_WARNING(
"Cons " <<
n <<
" has a max radius 1 of " << theCons->getRMax1() <<
" - will use std::abs.");}
267 if (theCons->getRMax2()<0.){
ATH_MSG_WARNING(
"Cons " <<
n <<
" has a max radius 2 of " << theCons->getRMax2() <<
" - will use std::abs.");}
268 if (theCons->getRMin1()<0.){
ATH_MSG_WARNING(
"Cons " <<
n <<
" has a min radius 1 of " << theCons->getRMin1());}
269 if (theCons->getRMin2()<0.){
ATH_MSG_WARNING(
"Cons " <<
n <<
" has a min radius 2 of " << theCons->getRMin2());}
270 if (theCons->getDZ()<=0){
ATH_MSG_WARNING(
"Cons " <<
n <<
" has a DZ of " << theCons->getDZ() <<
" - will use std::abs.");}
271 if (theCons->getRMax1()<=0. && theCons->getRMax2()<=0.){
ATH_MSG_WARNING(
"Cons " <<
n <<
" has a max radius 1 of " << theCons->getRMax1()
272 <<
" and a max radius 2 of " << theCons->getRMax2() <<
" - will use std::abs.");}
273 theSolid =
new G4Cons(
n,
275 std::abs(theCons->getRMax1()),
277 std::abs(theCons->getRMax2()),
278 std::abs(theCons->getDZ()),
285 else if(geoShape->typeID() == GeoPara::getClassTypeID())
287 const GeoPara* thePara =
dynamic_cast<const GeoPara*
>(geoShape);
288 if (
nullptr==thePara)
throw std::runtime_error(
"TypeID did not match cast for para");
289 if (
n.empty())
n=
"G4Para";
290 if (thePara->getXHalfLength()<=0.){
ATH_MSG_WARNING(
"Para " <<
n <<
" has an x side of " << thePara->getXHalfLength() <<
" - using std::abs.");}
291 if (thePara->getYHalfLength()<=0.){
ATH_MSG_WARNING(
"Para " <<
n <<
" has an y side of " << thePara->getYHalfLength() <<
" - using std::abs.");}
292 if (thePara->getZHalfLength()<=0.){
ATH_MSG_WARNING(
"Para " <<
n <<
" has an z side of " << thePara->getZHalfLength() <<
" - using std::abs.");}
293 theSolid =
new G4Para(
n,
294 std::abs(thePara->getXHalfLength()),
295 std::abs(thePara->getYHalfLength()),
296 std::abs(thePara->getZHalfLength()),
304 else if(geoShape->typeID() == GeoPgon::getClassTypeID())
306 const GeoPgon* thePgon =
dynamic_cast<const GeoPgon*
>(geoShape);
307 if (
nullptr==thePgon)
throw std::runtime_error(
"TypeID did not match cast for pgon");
310 unsigned nPlanes = thePgon->getNPlanes();
311 auto rInner = std::make_unique<double[]>(nPlanes);
312 auto rOuter = std::make_unique<double[]>(nPlanes);
313 double alpha = thePgon->getDPhi()/(2*thePgon->getNSides());
314 for (
unsigned int index=0; index<static_cast<unsigned int>(nPlanes);
index++) {
319 theSolid =
new G4Polyhedra(
n.empty()?
"G4Polyhedra":std::move(
n),
322 thePgon->getNSides(),
324 thePgon->getZPlaneBuff(),
331 else if(geoShape->typeID() == GeoTrap::getClassTypeID())
333 const GeoTrap* theTrap =
dynamic_cast<const GeoTrap*
>(geoShape);
334 if (
nullptr==theTrap)
throw std::runtime_error(
"TypeID did not match cast for trap");
335 if (
n.empty())
n=
"G4Trap";
336 if (theTrap->getZHalfLength()<=0.){
ATH_MSG_WARNING(
"Trap " <<
n <<
" has an z side of " << theTrap->getZHalfLength() <<
" - using std::abs.");}
337 theSolid =
new G4Trap(
n,
338 std::abs(theTrap->getZHalfLength()),
342 theTrap->getDxdyndzn(),
343 theTrap->getDxdypdzn(),
344 theTrap->getAngleydzn(),
346 theTrap->getDxdyndzp(),
347 theTrap->getDxdypdzp(),
348 theTrap->getAngleydzp());
353 else if(geoShape->typeID() == GeoSimplePolygonBrep::getClassTypeID())
355 const GeoSimplePolygonBrep* theBrep =
dynamic_cast<const GeoSimplePolygonBrep*
>(geoShape);
356 if (
nullptr==theBrep)
throw std::runtime_error(
"TypeID did not match cast for brep");
357 if (
n.empty())
n=
"G4ExtrudedSolid";
358 double dz = theBrep->getDZ();
361 G4TwoVector off(0,0);
362 std::vector<G4TwoVector> polygon;
366 polygon.push_back(G4TwoVector(theBrep->getXVertex(
nVertices-1-
i),theBrep->getYVertex(
nVertices-1-
i)));
368 theSolid =
new G4ExtrudedSolid(
n,polygon,dz,off,1,off,1);
373 else if(geoShape->typeID() == GeoTessellatedSolid::getClassTypeID())
375 const GeoTessellatedSolid* theTessellated =
dynamic_cast<const GeoTessellatedSolid*
>(geoShape);
376 if (
nullptr==theTessellated)
throw std::runtime_error(
"TypeID did not match cast for tessellated solid");
377 if(
n.empty())
n=
"G4TessellatedSolid";
379 G4TessellatedSolid* g4Tessellated =
new G4TessellatedSolid(
n);
380 for(
size_t i=0;
i<theTessellated->getNumberOfFacets(); ++
i) {
381 GeoFacet* geoFacet = theTessellated->getFacet(
i);
382 G4FacetVertexType
vertexType = (geoFacet->getVertexType()==GeoFacet::ABSOLUTE? ABSOLUTE : RELATIVE);
383 G4VFacet* g4Facet(
nullptr);
384 if(geoFacet->getNumberOfVertices()==3)
396 g4Tessellated->AddFacet(g4Facet);
398 g4Tessellated->SetSolidClosed(
true);
399 theSolid = g4Tessellated;
404 else if(geoShape->typeID() == GeoEllipticalTube::getClassTypeID())
406 const GeoEllipticalTube* theEltube =
dynamic_cast<const GeoEllipticalTube*
>(geoShape);
407 if (
nullptr==theEltube)
throw std::runtime_error(
"TypeID did not match cast for elliptical tube");
408 if (
n.empty())
n=
"G4EllipticalTube";
410 if (theEltube->getXHalfLength()<=0.){
ATH_MSG_WARNING(
"Eltube " <<
n <<
" has an x side of " << theEltube->getXHalfLength() <<
" - using std::abs.");}
411 if (theEltube->getYHalfLength()<=0.){
ATH_MSG_WARNING(
"Eltube " <<
n <<
" has an y side of " << theEltube->getYHalfLength() <<
" - using std::abs.");}
412 if (theEltube->getZHalfLength()<=0.){
ATH_MSG_WARNING(
"Eltube " <<
n <<
" has an z side of " << theEltube->getZHalfLength() <<
" - using std::abs.");}
413 G4EllipticalTube* g4Eltube =
new G4EllipticalTube(
n
414 ,std::abs(theEltube->getXHalfLength())
415 ,std::abs(theEltube->getYHalfLength())
416 ,std::abs(theEltube->getZHalfLength()));
422 else if(geoShape->typeID() == GeoTorus::getClassTypeID() ) {
423 const GeoTorus* theTorus =
dynamic_cast<const GeoTorus*
> (geoShape);
424 if (
nullptr==theTorus)
throw std::runtime_error(
"TypeID did not match cast for torus");
425 if (
n.empty())
n=
"G4Torus";
427 theSolid =
new G4Torus(
n,
432 theTorus->getDPhi());
437 else if(geoShape->typeID() == GeoGenericTrap::getClassTypeID()) {
438 const GeoGenericTrap* theGenTrap =
dynamic_cast<const GeoGenericTrap*
>(geoShape);
439 if (
nullptr==theGenTrap)
throw std::runtime_error(
"TypeID did not match cast for generic trap");
440 if (
n.empty())
n=
"G4GenericTrap";
441 if (theGenTrap->getZHalfLength()<=0.){
ATH_MSG_WARNING(
"GenTrap " <<
n <<
" has an z side of " << theGenTrap->getZHalfLength() <<
" - using std::abs.");}
444 std::vector<CLHEP::Hep2Vector> clhepVertices;
445 clhepVertices.reserve(theGenTrap->getVertices().size());
447 clhepVertices.push_back(CLHEP::Hep2Vector(geoVertex.x(),geoVertex.y()));
450 G4GenericTrap* g4GenTrap =
new G4GenericTrap(
n
451 ,std::abs(theGenTrap->getZHalfLength())
453 theSolid = g4GenTrap;
462 else if (geoShape->typeID() == GeoShapeShift::getClassTypeID() )
464 const GeoShapeShift* theShapeShift =
dynamic_cast<const GeoShapeShift*
> (geoShape);
465 if (
nullptr==theShapeShift)
throw std::runtime_error(
"TypeID did not match cast for shape shift");
466 if (
n.empty())
n=
"DisplacedSolid";
467 G4VSolid * undisplacedSolid = Build(theShapeShift->getOp());
473 else if (geoShape->typeID() == GeoShapeUnion::getClassTypeID() )
475 const GeoShapeUnion* theUnion =
dynamic_cast<const GeoShapeUnion*
> (geoShape);
476 if (
nullptr==theUnion)
throw std::runtime_error(
"TypeID did not match cast for union");
477 if (
n.empty())
n=
"Union";
478 solidA = Build(theUnion->getOpA());
479 solidB = Build(theUnion->getOpB());
480 theSolid =
new G4UnionSolid(
n, solidA, solidB);
485 else if (geoShape->typeID() == GeoShapeIntersection::getClassTypeID() )
487 const GeoShapeIntersection* theIntersection =
dynamic_cast<const GeoShapeIntersection*
>(geoShape);
488 if (
nullptr==theIntersection)
throw std::runtime_error(
"TypeID did not match cast for intersection");
489 if (
n.empty())
n=
"Intersection";
490 solidA = Build(theIntersection->getOpA());
491 solidB = Build(theIntersection->getOpB());
492 theSolid =
new G4IntersectionSolid(
n, solidA, solidB);
497 else if (geoShape->typeID() == GeoShapeSubtraction::getClassTypeID() )
499 const GeoShapeSubtraction* theSubtraction =
dynamic_cast<const GeoShapeSubtraction*
>(geoShape);
500 if (
nullptr==theSubtraction)
throw std::runtime_error(
"TypeID did not match cast for subtraction");
501 if (
n.empty())
n=
"Subtraction";
502 solidA = Build(theSubtraction->getOpA());
503 solidB = Build(theSubtraction->getOpB());
504 theSolid =
new G4SubtractionSolid(
n, solidA, solidB);
509 else if(geoShape->typeID() == GeoUnidentifiedShape::getClassTypeID())
511 const GeoUnidentifiedShape* customShape =
dynamic_cast<const GeoUnidentifiedShape*
> (geoShape);
512 if (
nullptr==customShape)
throw std::runtime_error(
"TypeID did not match cast for custom shape");
513 if (customShape->name()==
"LArCustomShape") {
517 ISvcLocator* svcLocator = Gaudi::svcLocator();
519 SmartIF<IGeoModelSvc> geoModel{svcLocator->service (
"GeoModelSvc")};
522 "Geo2G4SolidFactory",
"AccessGeoModel", FatalException,
523 "Build cannot access GeoModelSvc");
525 SmartIF<IGeoDbTagSvc> geoDbTagSvc{svcLocator->service (
"GeoDbTagSvc")};
526 if ( !geoDbTagSvc ) {
528 "Geo2G4SolidFactory",
"AccessDbTagSvc", FatalException,
529 "Build cannot access DbTagSvc");
532 SmartIF<IRDBAccessSvc> pAccessSvc{svcLocator->service(geoDbTagSvc->getParamSvcName())};
535 "Geo2G4SolidFactory",
"AccessAccessSvc", FatalException,
536 "Build cannot access AccessSvc");
543 std::string customName = customShape->asciiData();
544 customSolidMap::const_iterator
it = customSolids.find(customName);
545 if(
it!=customSolids.end())
546 theSolid =
it->second;
550 if(customName.find(
"Slice") != std::string::npos){
551 theSolid = createLArWheelSliceSolid(customShape,emecData);
553 theSolid = createLArWheelSolid(customName, s_lwsTypes.at(customName) ,emecData);
555 if (
nullptr == theSolid ) {
556 std::string
error = std::string(
"Can't create LArWheelSolid for name ") + customName +
" in Geo2G4SolidFactory::Build";
557 throw std::runtime_error(
error);
560 if(theSolid !=
nullptr) customSolids[customName] = theSolid;
569 ATH_MSG_FATAL(
"Sorry this solid is not yet implemented... ");
575 sharedShapes[geoShape] = theSolid;