154 G4VSolid* theSolid(
nullptr);
158 if(sharedShapes.find(geoShape)!=sharedShapes.end())
159 return sharedShapes[geoShape];
162 G4VSolid* solidA(
nullptr);
163 G4VSolid* solidB(
nullptr);
166 double* zPlane(
nullptr);
167 double* rInner(
nullptr);
168 double* rOuter(
nullptr);
170 std::string
n = std::move(
name);
175 if(geoShape->typeID() == GeoBox::getClassTypeID() )
177 const GeoBox* theBox =
dynamic_cast<const GeoBox*
> (geoShape);
178 if (
nullptr==theBox)
throw std::runtime_error(
"TypeID did not match cast for box");
179 if (
n.empty())
n=
"G4Box";
180 if (theBox->getXHalfLength()<=0.){
ATH_MSG_WARNING(
"Box " <<
n <<
" has an x side of " << theBox->getXHalfLength() <<
" - using std::abs.");}
181 if (theBox->getYHalfLength()<=0.){
ATH_MSG_WARNING(
"Box " <<
n <<
" has an y side of " << theBox->getYHalfLength() <<
" - using std::abs.");}
182 if (theBox->getZHalfLength()<=0.){
ATH_MSG_WARNING(
"Box " <<
n <<
" has an z side of " << theBox->getZHalfLength() <<
" - using std::abs.");}
183 theSolid =
new G4Box(
n,
184 std::abs(theBox->getXHalfLength()),
185 std::abs(theBox->getYHalfLength()),
186 std::abs(theBox->getZHalfLength()));
191 else if(geoShape->typeID() == GeoTube::getClassTypeID() )
193 const GeoTube* theTube =
dynamic_cast<const GeoTube*
> (geoShape);
194 if (
nullptr==theTube)
throw std::runtime_error(
"TypeID did not match cast for tube");
195 if (
n.empty())
n=
"G4Tube";
196 if (theTube->getRMax()<=0.){
ATH_MSG_WARNING(
"Tube " <<
n <<
" has a max radius of " << theTube->getRMax() <<
" - using std::abs.");}
197 if (theTube->getZHalfLength()<=0.){
ATH_MSG_WARNING(
"Tube " <<
n <<
" has a z half length of " << theTube->getZHalfLength() <<
" - using std::abs.");}
198 if (theTube->getRMax()<theTube->getRMin()){
ATH_MSG_WARNING(
"Tube " <<
n <<
" has a max radius of " << theTube->getRMax() <<
" and a min radius of " << theTube->getRMin());}
199 theSolid =
new G4Tubs(
n,
201 std::abs(theTube->getRMax()),
202 std::abs(theTube->getZHalfLength()),
208 else if(geoShape->typeID() == GeoTubs::getClassTypeID() )
210 const GeoTubs* theTubs =
dynamic_cast<const GeoTubs*
> (geoShape);
211 if (
nullptr==theTubs)
throw std::runtime_error(
"TypeID did not match cast for tubs");
212 if (
n.empty())
n=
"G4Tubs";
213 if (theTubs->getRMin()<0.){
ATH_MSG_WARNING(
"Tubs " <<
n <<
" has a min radius of " << theTubs->getRMax());}
214 if (theTubs->getRMax()<=0.){
ATH_MSG_WARNING(
"Tubs " <<
n <<
" has a max radius of " << theTubs->getRMax() <<
" - using std::abs.");}
215 if (theTubs->getZHalfLength()<=0.){
ATH_MSG_WARNING(
"Tubs " <<
n <<
" has a half length of " << theTubs->getZHalfLength() <<
" - using std::abs.");}
216 if (theTubs->getRMax()<theTubs->getRMin()){
ATH_MSG_WARNING(
"Tubs " <<
n <<
" has a max radius of " << theTubs->getRMax() <<
" and a min radius of " << theTubs->getRMin());}
217 if (theTubs->getDPhi()<=0.){
ATH_MSG_WARNING(
"Tubs " <<
n <<
" has a dPhi of " << theTubs->getDPhi());}
218 theSolid =
new G4Tubs(
n,
220 std::abs(theTubs->getRMax()),
221 std::abs(theTubs->getZHalfLength()),
228 else if(geoShape->typeID() == GeoTrd::getClassTypeID() )
230 const GeoTrd* theTrd =
dynamic_cast<const GeoTrd*
> (geoShape);
231 if (
nullptr==theTrd)
throw std::runtime_error(
"TypeID did not match cast for trd");
232 if (
n.empty())
n=
"G4Trd";
233 if (theTrd->getXHalfLength1()<0.){
ATH_MSG_WARNING(
"Trd " <<
n <<
" has a x half length 1 of " << theTrd->getXHalfLength1() <<
" - using std::abs.");}
234 if (theTrd->getXHalfLength2()<0.){
ATH_MSG_WARNING(
"Trd " <<
n <<
" has a x half length 2 of " << theTrd->getXHalfLength2() <<
" - using std::abs.");}
235 if (theTrd->getYHalfLength1()<0.){
ATH_MSG_WARNING(
"Trd " <<
n <<
" has a y half length 1 of " << theTrd->getYHalfLength1() <<
" - using std::abs.");}
236 if (theTrd->getYHalfLength2()<0.){
ATH_MSG_WARNING(
"Trd " <<
n <<
" has a y half length 2 of " << theTrd->getYHalfLength2() <<
" - using std::abs.");}
237 if (theTrd->getZHalfLength()<=0.){
ATH_MSG_WARNING(
"Trd " <<
n <<
" has a z half length of " << theTrd->getZHalfLength() <<
" - using std::abs.");}
238 if (theTrd->getXHalfLength1()<=0. && theTrd->getXHalfLength2()<=0.){
ATH_MSG_WARNING(
"Trd " <<
n <<
" has an x half length 1 of " << theTrd->getXHalfLength1()
239 <<
" and an x half length 2 of " << theTrd->getXHalfLength2() <<
" - using std::abs.");}
240 if (theTrd->getYHalfLength1()<=0. && theTrd->getYHalfLength2()<=0.){
ATH_MSG_WARNING(
"Trd " <<
n <<
" has a y half length 1 of " << theTrd->getYHalfLength1()
241 <<
" and a y half length 2 of " << theTrd->getYHalfLength2() <<
" - using std::abs.");}
242 theSolid =
new G4Trd(
n,
243 std::abs(theTrd->getXHalfLength1()),
244 std::abs(theTrd->getXHalfLength2()),
245 std::abs(theTrd->getYHalfLength1()),
246 std::abs(theTrd->getYHalfLength2()),
247 std::abs(theTrd->getZHalfLength()));
252 else if(geoShape->typeID() == GeoPcon::getClassTypeID())
254 const GeoPcon* thePcon =
dynamic_cast<const GeoPcon*
>(geoShape);
255 if (
nullptr==thePcon)
throw std::runtime_error(
"TypeID did not match cast for pcon");
256 if (
n.empty())
n=
"G4Polycone";
257 nPlanes =
static_cast<int>(thePcon->getNPlanes());
258 zPlane =
new double[nPlanes];
259 rInner =
new double[nPlanes];
260 rOuter =
new double[nPlanes];
261 for (
unsigned int index=0; index<static_cast<unsigned int>(nPlanes);
index++)
267 if (rOuter[
index]<=0.){
268 ATH_MSG_WARNING(
"PCon " <<
n <<
" has an outer radius of " << rOuter[
index] <<
" for slice " <<
index <<
" of " << nPlanes <<
" - using std::abs.");
273 theSolid =
new G4Polycone(
n,
284 else if(geoShape->typeID() == GeoCons::getClassTypeID())
286 const GeoCons* theCons =
dynamic_cast<const GeoCons*
>(geoShape);
287 if (
nullptr==theCons)
throw std::runtime_error(
"TypeID did not match cast for cons");
288 if (
n.empty())
n=
"G4Cons";
289 if (theCons->getRMax1()<0.){
ATH_MSG_WARNING(
"Cons " <<
n <<
" has a max radius 1 of " << theCons->getRMax1() <<
" - will use std::abs.");}
290 if (theCons->getRMax2()<0.){
ATH_MSG_WARNING(
"Cons " <<
n <<
" has a max radius 2 of " << theCons->getRMax2() <<
" - will use std::abs.");}
291 if (theCons->getRMin1()<0.){
ATH_MSG_WARNING(
"Cons " <<
n <<
" has a min radius 1 of " << theCons->getRMin1());}
292 if (theCons->getRMin2()<0.){
ATH_MSG_WARNING(
"Cons " <<
n <<
" has a min radius 2 of " << theCons->getRMin2());}
293 if (theCons->getDZ()<=0){
ATH_MSG_WARNING(
"Cons " <<
n <<
" has a DZ of " << theCons->getDZ() <<
" - will use std::abs.");}
294 if (theCons->getRMax1()<=0. && theCons->getRMax2()<=0.){
ATH_MSG_WARNING(
"Cons " <<
n <<
" has a max radius 1 of " << theCons->getRMax1()
295 <<
" and a max radius 2 of " << theCons->getRMax2() <<
" - will use std::abs.");}
296 theSolid =
new G4Cons(
n,
298 std::abs(theCons->getRMax1()),
300 std::abs(theCons->getRMax2()),
301 std::abs(theCons->getDZ()),
308 else if(geoShape->typeID() == GeoPara::getClassTypeID())
310 const GeoPara* thePara =
dynamic_cast<const GeoPara*
>(geoShape);
311 if (
nullptr==thePara)
throw std::runtime_error(
"TypeID did not match cast for para");
312 if (
n.empty())
n=
"G4Para";
313 if (thePara->getXHalfLength()<=0.){
ATH_MSG_WARNING(
"Para " <<
n <<
" has an x side of " << thePara->getXHalfLength() <<
" - using std::abs.");}
314 if (thePara->getYHalfLength()<=0.){
ATH_MSG_WARNING(
"Para " <<
n <<
" has an y side of " << thePara->getYHalfLength() <<
" - using std::abs.");}
315 if (thePara->getZHalfLength()<=0.){
ATH_MSG_WARNING(
"Para " <<
n <<
" has an z side of " << thePara->getZHalfLength() <<
" - using std::abs.");}
316 theSolid =
new G4Para(
n,
317 std::abs(thePara->getXHalfLength()),
318 std::abs(thePara->getYHalfLength()),
319 std::abs(thePara->getZHalfLength()),
327 else if(geoShape->typeID() == GeoPgon::getClassTypeID())
329 const GeoPgon* thePgon =
dynamic_cast<const GeoPgon*
>(geoShape);
330 if (
nullptr==thePgon)
throw std::runtime_error(
"TypeID did not match cast for pgon");
331 if (
n.empty())
n=
"G4Polyhedra";
332 nPlanes =
static_cast<int>(thePgon->getNPlanes());
333 zPlane =
new double[nPlanes];
334 rInner =
new double[nPlanes];
335 rOuter =
new double[nPlanes];
336 double alpha = thePgon->getDPhi()/(2*thePgon->getNSides());
337 for (
unsigned int index=0; index<static_cast<unsigned int>(nPlanes);
index++)
343 if (rOuter[
index]<=0.){
344 ATH_MSG_WARNING(
"Pgon " <<
n <<
" has an outer radius of " << rOuter[
index] <<
" for slice " <<
index <<
" of " << nPlanes <<
" - using std::abs.");
349 theSolid =
new G4Polyhedra(
n,
352 thePgon->getNSides(),
361 else if(geoShape->typeID() == GeoTrap::getClassTypeID())
363 const GeoTrap* theTrap =
dynamic_cast<const GeoTrap*
>(geoShape);
364 if (
nullptr==theTrap)
throw std::runtime_error(
"TypeID did not match cast for trap");
365 if (
n.empty())
n=
"G4Trap";
366 if (theTrap->getZHalfLength()<=0.){
ATH_MSG_WARNING(
"Trap " <<
n <<
" has an z side of " << theTrap->getZHalfLength() <<
" - using std::abs.");}
367 theSolid =
new G4Trap(
n,
368 std::abs(theTrap->getZHalfLength()),
372 theTrap->getDxdyndzn(),
373 theTrap->getDxdypdzn(),
374 theTrap->getAngleydzn(),
376 theTrap->getDxdyndzp(),
377 theTrap->getDxdypdzp(),
378 theTrap->getAngleydzp());
383 else if(geoShape->typeID() == GeoSimplePolygonBrep::getClassTypeID())
385 const GeoSimplePolygonBrep* theBrep =
dynamic_cast<const GeoSimplePolygonBrep*
>(geoShape);
386 if (
nullptr==theBrep)
throw std::runtime_error(
"TypeID did not match cast for brep");
387 if (
n.empty())
n=
"G4ExtrudedSolid";
388 double dz = theBrep->getDZ();
391 G4TwoVector off(0,0);
392 std::vector<G4TwoVector> polygon;
396 polygon.push_back(G4TwoVector(theBrep->getXVertex(
nVertices-1-
i),theBrep->getYVertex(
nVertices-1-
i)));
398 theSolid =
new G4ExtrudedSolid(
n,polygon,dz,off,1,off,1);
403 else if(geoShape->typeID() == GeoTessellatedSolid::getClassTypeID())
405 const GeoTessellatedSolid* theTessellated =
dynamic_cast<const GeoTessellatedSolid*
>(geoShape);
406 if (
nullptr==theTessellated)
throw std::runtime_error(
"TypeID did not match cast for tessellated solid");
407 if(
n.empty())
n=
"G4TessellatedSolid";
409 G4TessellatedSolid* g4Tessellated =
new G4TessellatedSolid(
n);
410 for(
size_t i=0;
i<theTessellated->getNumberOfFacets(); ++
i) {
411 GeoFacet* geoFacet = theTessellated->getFacet(
i);
412 G4FacetVertexType
vertexType = (geoFacet->getVertexType()==GeoFacet::ABSOLUTE? ABSOLUTE : RELATIVE);
413 G4VFacet* g4Facet(
nullptr);
414 if(geoFacet->getNumberOfVertices()==3)
426 g4Tessellated->AddFacet(g4Facet);
428 g4Tessellated->SetSolidClosed(
true);
429 theSolid = g4Tessellated;
434 else if(geoShape->typeID() == GeoEllipticalTube::getClassTypeID())
436 const GeoEllipticalTube* theEltube =
dynamic_cast<const GeoEllipticalTube*
>(geoShape);
437 if (
nullptr==theEltube)
throw std::runtime_error(
"TypeID did not match cast for elliptical tube");
438 if (
n.empty())
n=
"G4EllipticalTube";
440 if (theEltube->getXHalfLength()<=0.){
ATH_MSG_WARNING(
"Eltube " <<
n <<
" has an x side of " << theEltube->getXHalfLength() <<
" - using std::abs.");}
441 if (theEltube->getYHalfLength()<=0.){
ATH_MSG_WARNING(
"Eltube " <<
n <<
" has an y side of " << theEltube->getYHalfLength() <<
" - using std::abs.");}
442 if (theEltube->getZHalfLength()<=0.){
ATH_MSG_WARNING(
"Eltube " <<
n <<
" has an z side of " << theEltube->getZHalfLength() <<
" - using std::abs.");}
443 G4EllipticalTube* g4Eltube =
new G4EllipticalTube(
n
444 ,std::abs(theEltube->getXHalfLength())
445 ,std::abs(theEltube->getYHalfLength())
446 ,std::abs(theEltube->getZHalfLength()));
452 else if(geoShape->typeID() == GeoTorus::getClassTypeID() ) {
453 const GeoTorus* theTorus =
dynamic_cast<const GeoTorus*
> (geoShape);
454 if (
nullptr==theTorus)
throw std::runtime_error(
"TypeID did not match cast for torus");
455 if (
n.empty())
n=
"G4Torus";
457 theSolid =
new G4Torus(
n,
462 theTorus->getDPhi());
467 else if(geoShape->typeID() == GeoGenericTrap::getClassTypeID()) {
468 const GeoGenericTrap* theGenTrap =
dynamic_cast<const GeoGenericTrap*
>(geoShape);
469 if (
nullptr==theGenTrap)
throw std::runtime_error(
"TypeID did not match cast for generic trap");
470 if (
n.empty())
n=
"G4GenericTrap";
471 if (theGenTrap->getZHalfLength()<=0.){
ATH_MSG_WARNING(
"GenTrap " <<
n <<
" has an z side of " << theGenTrap->getZHalfLength() <<
" - using std::abs.");}
474 std::vector<CLHEP::Hep2Vector> clhepVertices;
475 clhepVertices.reserve(theGenTrap->getVertices().size());
477 clhepVertices.push_back(CLHEP::Hep2Vector(geoVertex.x(),geoVertex.y()));
480 G4GenericTrap* g4GenTrap =
new G4GenericTrap(
n
481 ,std::abs(theGenTrap->getZHalfLength())
483 theSolid = g4GenTrap;
492 else if (geoShape->typeID() == GeoShapeShift::getClassTypeID() )
494 const GeoShapeShift* theShapeShift =
dynamic_cast<const GeoShapeShift*
> (geoShape);
495 if (
nullptr==theShapeShift)
throw std::runtime_error(
"TypeID did not match cast for shape shift");
496 if (
n.empty())
n=
"DisplacedSolid";
497 G4VSolid * undisplacedSolid = Build(theShapeShift->getOp());
503 else if (geoShape->typeID() == GeoShapeUnion::getClassTypeID() )
505 const GeoShapeUnion* theUnion =
dynamic_cast<const GeoShapeUnion*
> (geoShape);
506 if (
nullptr==theUnion)
throw std::runtime_error(
"TypeID did not match cast for union");
507 if (
n.empty())
n=
"Union";
508 solidA = Build(theUnion->getOpA());
509 solidB = Build(theUnion->getOpB());
510 theSolid =
new G4UnionSolid(
n, solidA, solidB);
515 else if (geoShape->typeID() == GeoShapeIntersection::getClassTypeID() )
517 const GeoShapeIntersection* theIntersection =
dynamic_cast<const GeoShapeIntersection*
>(geoShape);
518 if (
nullptr==theIntersection)
throw std::runtime_error(
"TypeID did not match cast for intersection");
519 if (
n.empty())
n=
"Intersection";
520 solidA = Build(theIntersection->getOpA());
521 solidB = Build(theIntersection->getOpB());
522 theSolid =
new G4IntersectionSolid(
n, solidA, solidB);
527 else if (geoShape->typeID() == GeoShapeSubtraction::getClassTypeID() )
529 const GeoShapeSubtraction* theSubtraction =
dynamic_cast<const GeoShapeSubtraction*
>(geoShape);
530 if (
nullptr==theSubtraction)
throw std::runtime_error(
"TypeID did not match cast for subtraction");
531 if (
n.empty())
n=
"Subtraction";
532 solidA = Build(theSubtraction->getOpA());
533 solidB = Build(theSubtraction->getOpB());
534 theSolid =
new G4SubtractionSolid(
n, solidA, solidB);
539 else if(geoShape->typeID() == GeoUnidentifiedShape::getClassTypeID())
541 const GeoUnidentifiedShape* customShape =
dynamic_cast<const GeoUnidentifiedShape*
> (geoShape);
542 if (
nullptr==customShape)
throw std::runtime_error(
"TypeID did not match cast for custom shape");
543 if (customShape->name()==
"LArCustomShape") {
547 ISvcLocator* svcLocator = Gaudi::svcLocator();
550 if (svcLocator->service (
"GeoModelSvc",geoModel) !=StatusCode::SUCCESS) {
552 "Geo2G4SolidFactory",
"AccessGeoModel", FatalException,
553 "Build cannot access GeoModelSvc");
556 if ( svcLocator->service (
"GeoDbTagSvc",geoDbTagSvc)!=StatusCode::SUCCESS ) {
558 "Geo2G4SolidFactory",
"AccessDbTagSvc", FatalException,
559 "Build cannot access DbTagSvc");
563 if ( svcLocator->service(geoDbTagSvc->getParamSvcName(),pAccessSvc)!=StatusCode::SUCCESS) {
565 "Geo2G4SolidFactory",
"AccessAccessSvc", FatalException,
566 "Build cannot access AccessSvc");
573 std::string customName = customShape->asciiData();
574 customSolidMap::const_iterator
it = customSolids.find(customName);
575 if(
it!=customSolids.end())
576 theSolid =
it->second;
580 if(customName.find(
"Slice") != std::string::npos){
581 theSolid = createLArWheelSliceSolid(customShape,emecData);
583 theSolid = createLArWheelSolid(customName, s_lwsTypes.at(customName) ,emecData);
585 if (
nullptr == theSolid ) {
586 std::string
error = std::string(
"Can't create LArWheelSolid for name ") + customName +
" in Geo2G4SolidFactory::Build";
587 throw std::runtime_error(
error);
590 if(theSolid !=
nullptr) customSolids[customName] = theSolid;
599 ATH_MSG_FATAL(
"Sorry this solid is not yet implemented... ");
605 sharedShapes[geoShape] = theSolid;