19 #include <TGeoScaledShape.h>
20 #include <TGeoShapeAssembly.h>
48 Solid solid =
Scale(shape.ptr(), scale.x(1.0), scale.y(1.0), scale.z(1.0));
49 if ( e.
hasAttr(
_U(name)) ) solid->SetName(e.
attr<std::string>(
_U(name)).c_str());
69 if ( e.
hasAttr(
_U(name)) ) solid->SetName(e.
attr<std::string>(
_U(name)).c_str());
88 Solid solid =
Box(dim.dx(),dim.dy(),dim.dz());
89 if ( e.
hasAttr(
_U(name)) ) solid->SetName(e.
attr<std::string>(
_U(name)).c_str());
112 double p[3] = { point.x(), point.y(), point.z()};
113 double n[3] = { normal.x(), normal.y(), normal.z()};
115 if ( e.
hasAttr(
_U(name)) ) solid->SetName(e.
attr<std::string>(
_U(name)).c_str());
134 double rmi1 = e.rmin1(0.0), rma1 = e.rmax1();
135 Solid solid =
Cone(e.z(0.0), rmi1, rma1, e.rmin2(rmi1), e.rmax2(rma1));
136 if ( e.
hasAttr(
_U(name)) ) solid->SetName(e.
attr<std::string>(
_U(name)).c_str());
161 std::vector<double> rmin,rmax,z;
162 double start = e.startphi(0e0), deltaphi = e.deltaphi(2*
M_PI);
165 rmin.emplace_back(plane.rmin(0.0));
166 rmax.emplace_back(plane.rmax());
167 z.emplace_back(plane.z());
170 throw std::runtime_error(
"PolyCone Shape> Not enough Z planes. minimum is 2!");
173 if ( e.
hasAttr(
_U(name)) ) solid->SetName(e.
attr<std::string>(
_U(name)).c_str());
204 if ( aphi || bphi ) {
205 double phi1 = e.phi1(0.0);
206 double phi2 = e.phi2(2*
M_PI);
208 solid =
ConeSegment(e.dz(),e.rmin1(0.0),e.rmax1(),e.rmin2(0.0),e.rmax2(),phi1,phi2);
211 double start_phi = e.startphi(0.0);
212 double delta_phi = e.deltaphi(2*
M_PI);
213 while ( start_phi > 2.0*
M_PI ) start_phi -= 2.0*
M_PI;
215 solid =
ConeSegment(e.dz(),e.rmin1(0.0),e.rmax1(),e.rmin2(0.0),e.rmax2(),start_phi,start_phi+delta_phi);
217 if ( e.
hasAttr(
_U(name)) ) solid->SetName(e.
attr<std::string>(
_U(name)).c_str());
248 if ( aphi || bphi ) {
249 double phi1 = e.phi1(0.0);
250 double phi2 = e.phi2(2*
M_PI);
251 solid =
Tube(e.rmin(0.0),e.rmax(),e.dz(0.0),phi1, phi2);
254 double phi1 = e.startphi(0.0);
255 double phi2 = phi1 + e.deltaphi(2*
M_PI);
256 solid =
Tube(e.rmin(0.0),e.rmax(),e.dz(0.0),phi1,phi2);
258 if ( e.
hasAttr(
_U(name)) ) solid->SetName(e.
attr<std::string>(
_U(name)).c_str());
273 double zpos = 0.0, zneg = 0.0;
275 nseg = e.nsegments();
278 zneg = -1.0*(zpos = e.dz());
284 solid =
TwistedTube(e.twist(0.0), e.rmin(0.0),e.rmax(),zneg, zpos, nseg, e.deltaphi(2*
M_PI));
286 if ( e.
hasAttr(
_U(name)) ) solid->SetName(e.
attr<std::string>(
_U(name)).c_str());
308 if ( e.
hasAttr(
_U(name)) ) solid->SetName(e.
attr<std::string>(
_U(name)).c_str());
322 if ( e.
hasAttr(
_U(name)) ) solid->SetName(e.
attr<std::string>(
_U(name)).c_str());
335 double sp = e.startphi(0.0), dp = e.deltaphi(2*
M_PI);
340 if ( e.
hasAttr(
_U(name)) ) solid->SetName(e.
attr<std::string>(
_U(name)).c_str());
379 solid =
Trap(e.z(0.0),e.theta(0),e.phi(0),y1,x1,x2,e.alpha1(0),y2,x3,x4,e.alpha2(0));
381 if ( e.
hasAttr(
_U(name)) ) solid->SetName(e.
attr<std::string>(
_U(name)).c_str());
395 if ( e.
hasAttr(
_U(name)) ) solid->SetName(e.
attr<std::string>(
_U(name)).c_str());
413 Solid solid =
Trd1(e.x1(),e.x2(),e.y(),e.z(0.0));
414 if ( e.
hasAttr(
_U(name)) ) solid->SetName(e.
attr<std::string>(
_U(name)).c_str());
432 Solid solid =
Trd2(e.x1(),e.x2(),e.y1(),e.y2(),e.z(0.0));
433 if ( e.
hasAttr(
_U(name)) ) solid->SetName(e.
attr<std::string>(
_U(name)).c_str());
462 if ( aphi || bphi ) {
463 double phi1 = e.phi1(0.0);
464 double phi2 = e.phi2(2*
M_PI);
466 solid =
Torus(e.r(), e.rmin(0.0), e.rmax(), phi1, phi2-phi1);
469 double start_phi = e.startphi(0.0);
470 double delta_phi = e.deltaphi(2*
M_PI);
471 while ( start_phi > 2.0*
M_PI ) start_phi -= 2.0*
M_PI;
473 solid =
Torus(e.r(), e.rmin(0.0), e.rmax(), start_phi, delta_phi);
475 if ( e.
hasAttr(
_U(name)) ) solid->SetName(e.
attr<std::string>(
_U(name)).c_str());
497 double startphi = e.phi(0e0);
498 double endphi = startphi + 2.*
M_PI;
499 double starttheta = e.theta(0e0);
500 double endtheta = starttheta +
M_PI;
503 startphi = e.startphi();
504 endphi = startphi + 2.*
M_PI;
509 endphi = startphi + e.deltaphi();
512 starttheta = e.starttheta();
513 endtheta = starttheta +
M_PI;
516 endtheta = e.endtheta();
518 endtheta = starttheta + e.deltatheta();
520 Solid solid =
Sphere(e.rmin(0e0), e.rmax(), starttheta, endtheta, startphi, endphi);
521 if ( e.
hasAttr(
_U(name)) ) solid->SetName(e.
attr<std::string>(
_U(name)).c_str());
540 if ( e.
hasAttr(
_U(name)) ) solid->SetName(e.
attr<std::string>(
_U(name)).c_str());
560 Solid solid =
Hyperboloid(e.rmin(), e.inner_stereo(), e.rmax(), e.outer_stereo(), e.dz());
561 if ( e.
hasAttr(
_U(name)) ) solid->SetName(e.
attr<std::string>(
_U(name)).c_str());
581 if ( e.
hasAttr(
_U(name)) ) solid->SetName(e.
attr<std::string>(
_U(name)).c_str());
602 std::vector<double> z, rmin, rmax;
605 rmin.emplace_back(plane.rmin());
606 rmax.emplace_back(plane.rmax());
607 z.emplace_back(plane.z());
609 Solid solid =
Polyhedra(e.numsides(),e.startphi(),e.deltaphi(),z,rmin,rmax);
610 if ( e.
hasAttr(
_U(name)) ) solid->SetName(e.
attr<std::string>(
_U(name)).c_str());
623 std::vector<double> pt_x, pt_y, sec_z, sec_x, sec_y, sec_scale;
624 for (
xml_coll_t sec(element,
_U(section)); sec; ++sec ) {
626 sec_z.emplace_back(section.attr<
double>(
_U(z)));
627 sec_x.emplace_back(section.attr<
double>(
_U(x)));
628 sec_y.emplace_back(section.attr<
double>(
_U(y)));
629 sec_scale.emplace_back(section.attr<
double>(
_U(scale),1.0));
633 pt_x.emplace_back(point.attr<
double>(
_U(x)));
634 pt_y.emplace_back(point.attr<
double>(
_U(y)));
637 if ( e.
hasAttr(
_U(name)) ) solid->SetName(e.
attr<std::string>(
_U(name)).c_str());
652 memset(&
v[0][0],0,
sizeof(
v));
659 if ( e.
hasAttr(
_U(name)) ) solid->SetName(e.
attr<std::string>(
_U(name)).c_str());
672 std::vector<TessellatedSolid::Vertex> vertices;
675 vertices.emplace_back(
v.x(),
v.y(),
v.z());
678 for (
xml_coll_t facet(element,
_U(facet)); facet; ++facet ) ++num_facets;
680 if ( e.
hasAttr(
_U(name)) ) solid->SetName(e.
attr<std::string>(
_U(name)).c_str());
681 for (
xml_coll_t facet(element,
_U(facet)); facet; ++facet ) {
683 size_t i0 = f.attr<
size_t>(
_U(v0));
684 size_t i1 = f.attr<
size_t>(
_U(v1));
685 size_t i2 = f.attr<
size_t>(
_U(v2));
686 if ( f.hasAttr(
_U(v3)) ) {
687 size_t i3 = f.attr<
size_t>(
_U(v3));
688 solid.
addFacet(vertices[i0], vertices[i1], vertices[i2], vertices[i3]);
691 solid.
addFacet(vertices[i0], vertices[i1], vertices[i2]);
721 std::string op = e.
attr<std::string>(
_U(operation)) ;
722 std::transform( op.begin(), op.end(), op.begin(), ::tolower);
726 bool useRot(
false), usePos(
false), useTrans(
false);
736 pos =
Position( x_pos.x(0.0),x_pos.y(0.0),x_pos.z(0.0) );
741 rot =
RotationZYX( x_rot.z(0.0),x_rot.y(0.0),x_rot.x(0.0) ) ;
744 if( op ==
"subtraction" ) {
749 else if( useRot && usePos ) {
759 else if( op ==
"union" ) {
764 else if( useRot && usePos )
767 resultSolid =
UnionSolid(solid1, solid2, rot);
769 resultSolid =
UnionSolid(solid1, solid2, pos);
773 else if( op ==
"intersection" ) {
778 else if( useRot && usePos )
789 throw std::runtime_error(std::string(
" create_BooleanShape - unknown operation given: ") + op +
790 std::string(
" - needs to be one of 'subtraction','union' or 'intersection' ") ) ;
792 Solid solid = resultSolid ;
793 if ( e.
hasAttr(
_U(name)) ) solid->SetName(e.
attr<std::string>(
_U(name)).c_str());
802 Solid tmp, solid, result;
807 std::string op = e.
attr<std::string>(
_U(operation)) ;
808 std::transform( op.begin(), op.end(), op.begin(), ::tolower);
812 std::string tag = x_elt.tag();
813 if ( tag ==
"shape" && !result.
isValid() ) {
815 if ( (attr=i.attr_nothrow(
_U(name))) ) result->SetName(i.attr<std::string>(attr).c_str());
818 else if ( tag ==
"shape" && !solid.
isValid() ) {
820 if ( (attr=i.attr_nothrow(
_U(name))) ) result->SetName(i.attr<std::string>(attr).c_str());
824 if ( tag ==
"position" ) {
825 if ( flag == 4 ) trafo = position * trafo;
826 else if ( flag == 5 ) trafo = (position * rotation) * trafo;
827 Position pos(x_elt.x(0), x_elt.y(0), x_elt.z(0));
832 else if ( tag ==
"positionRZPhi" ) {
833 if ( flag == 4 ) trafo = position * trafo;
834 else if ( flag == 5 ) trafo = (position * rotation) * trafo;
835 ROOT::Math::RhoZPhiVector pos(x_elt.r(0), x_elt.z(0), x_elt.phi(0));
840 else if ( tag ==
"transformation" ) {
841 if ( flag == 4 ) trafo = position * trafo;
842 else if ( flag == 5 ) trafo = (position * rotation) * trafo;
848 else if ( tag ==
"rotation" ) {
852 else if ( tag ==
"shape" ) {
854 if ( flag == 4 ) trafo = position * trafo;
855 else if ( flag == 5 ) trafo = (position * rotation) * trafo;
857 if( op ==
"subtraction" )
859 else if( op ==
"union" )
861 else if( op ==
"intersection" )
864 throw std::runtime_error(
" create_BooleanShape - unknown operation given: " + op +
865 " - needs to be one of 'subtraction','union' or 'intersection' ");
870 if ( (attr=i.attr_nothrow(
_U(name))) ) result->SetName(i.attr<std::string>(attr).c_str());
877 if ( flag == 4 ) trafo = position * trafo;
878 else if ( flag == 5 ) trafo = (position * rotation) * trafo;
879 if( op ==
"subtraction" )
881 else if( op ==
"union" )
883 else if( op ==
"intersection" )
886 throw std::runtime_error(
" create_BooleanShape - unknown operation given: " + op +
887 " - needs to be one of 'subtraction','union' or 'intersection' ");
893 std::string nam = element.
attr<std::string>(attr);
894 result->SetName(nam.c_str());
921 std::string typ = elt.
attr<std::string>(
_U(type));
928 iRot.GetComponents(elements);
930 r.SetMatrix(elements);
931 TGeoTranslation t(iTrans.x(), iTrans.y(), iTrans.z());
932 return new TGeoCombiTrans(t, r);
943 std::string name = x_det.nameStr();
951 printout(DEBUG,
"TestShape",
"+++ Create shape: %s build type is: %s",
953 if ( x_det.hasChild(
_U(material)) ) {
954 mat = description.
material(x_det.child(
_U(material)).attr<std::string>(
_U(name)));
955 printout(INFO,
"TestShape",
"+++ Volume material is %s", mat.
name());
957 for (
xml_coll_t itm(e,
_U(check)); itm; ++itm, ++count ) {
960 xml_dim_t pos (x_check.child(
_U(position),
false));
961 xml_dim_t rot (x_check.child(
_U(rotation),
false));
962 bool reflect = x_check.hasChild(
_U(reflect));
963 bool reflectZ = x_check.hasChild(
_U(reflect_z));
964 bool reflectY = x_check.hasChild(
_U(reflect_y));
965 bool reflectX = x_check.hasChild(
_U(reflect_x));
966 std::string shape_type = shape.typeStr();
970 if ( shape_type ==
"CAD_Assembly" || shape_type ==
"CAD_MultiVolume" ) {
972 solid = volume->GetShape();
974 else if ( shape_type ==
"StdVolume" ) {
976 solid = volume->GetShape();
978 else if ( shape_type ==
"GenVolume" ) {
980 solid = volume->GetShape();
986 if ( x_det.hasChild(
_U(sensitive)) ) {
987 std::string sens_type = x_det.child(
_U(sensitive)).attr<std::string>(
_U(type));
990 printout(INFO,
"TestShape",
"+++ Sensitive type is %s", sens_type.c_str());
993 solid->SetName(shape_type.c_str());
996 if ( pos.ptr() && rot.ptr() ) {
998 Position pos3D(pos.x(0),pos.y(0),pos.z(0));
1001 else if ( pos.ptr() ) {
1004 else if ( rot.ptr() ) {
1010 tr = tr *
Rotation3D(1., 0., 0., 0., 1., 0., 0., 0., -1.);
1013 tr = tr *
Rotation3D(-1.,0.,0.,0.,1.,0.,0.,0.,1.);
1016 tr = tr *
Rotation3D(1.,0.,0.,0.,-1.,0.,0.,0.,1.);
1019 tr = tr *
Rotation3D(1.,0.,0.,0.,1.,0.,0.,0.,-1.);
1021 pv = assembly.placeVolume(volume,tr);
1023 if ( x_check.hasAttr(
_U(
id)) ) {
1025 printout(INFO,
"TestShape",
"+++ Volume id is %d", x_check.id());
1027 const char* nam = solid->GetName();
1028 printout(INFO,
"TestShape",
"Created successfull shape of type: %s %c%s%c",
1029 shape_type.c_str(), nam ?
'[' :
' ', nam ? nam :
"" ,nam ?
']' :
' ');
1031 bool instance_test =
false;
1032 if ( shape_type ==
"CAD_Assembly" || shape_type ==
"CAD_MultiVolume" ) {
1033 solid->SetTitle(shape_type.c_str());
1034 instance_test =
true;
1036 else if ( 0 == strcasecmp(solid->GetTitle(),
BOX_TAG) )
1038 else if ( 0 == strcasecmp(solid->GetTitle(),
TUBE_TAG) )
1040 else if ( 0 == strcasecmp(solid->GetTitle(),
CUTTUBE_TAG) )
1042 else if ( 0 == strcasecmp(solid->GetTitle(),
CONE_TAG) )
1044 else if ( 0 == strcasecmp(solid->GetTitle(),
TRD1_TAG) )
1046 else if ( 0 == strcasecmp(solid->GetTitle(),
TRD2_TAG) )
1048 else if ( 0 == strcasecmp(solid->GetTitle(),
TORUS_TAG) )
1050 else if ( 0 == strcasecmp(solid->GetTitle(),
SPHERE_TAG) )
1052 else if ( 0 == strcasecmp(solid->GetTitle(),
HALFSPACE_TAG) )
1060 else if ( 0 == strcasecmp(solid->GetTitle(),
"PolyhedraRegular") )
1062 else if ( 0 == strcasecmp(solid->GetTitle(),
POLYHEDRA_TAG) )
1068 else if ( 0 == strcasecmp(solid->GetTitle(),
SCALE_TAG) )
1074 else if ( 0 == strcasecmp(solid->GetTitle(),
POLYCONE_TAG) )
1088 else if ( 0 == strcasecmp(solid->GetTitle(),
TRAP_TAG) ) {
1102 else if ( 0 == strcasecmp(solid->GetTitle(),
UNION_TAG) ) {
1137 if ( !instance_test || ::strcasecmp(shape_type.c_str(),solid->GetTitle()) != 0 ) {
1138 printout(ERROR,
"TestShape",
"BAD shape type: %s <-> %s Instance test: %s",
1139 shape_type.c_str(), solid->GetTitle(),
1140 instance_test ?
"OK" :
"FAILED");
1143 printout(INFO,
"TestShape",
"Correct shape type: %s %s <-> %s Instance test: %s",
1144 solid->GetName(), shape_type.c_str(), solid->GetTitle(),
"OK");
1148 xml_dim_t x_pos(x_reflect.child(
_U(position),
false));
1149 xml_dim_t x_rot(x_reflect.child(
_U(rotation),
false));
1150 DetElement full_detector(name+
"_full",100+x_det.id());
1151 Assembly full_assembly(name+
"_full");
1155 if ( x_rot ) refl_rot =
RotationZYX(x_rot.z(0),x_rot.y(0),x_rot.x(0));
1156 if ( x_pos ) refl_pos =
Position(x_pos.x(0),x_pos.y(0),x_pos.z(0));
1160 pv = full_assembly.placeVolume(assembly);
1161 full_detector.add(
det);
1162 det.setPlacement(pv);
1165 auto reflected =
det.reflect(name+
"_reflected",100+x_det.id());
1166 pv = full_assembly.placeVolume(reflected.second, refl_trafo);
1167 full_detector.add(reflected.first);
1168 reflected.first.setPlacement(pv);
1172 full_detector.setPlacement(pv);
1174 det = full_detector;
1179 det.setPlacement(pv);
1184 std::string typ = x_test.typeStr();
1185 const void* argv[] = { &e, &pv, 0};
1186 Ref_t result = (
NamedObject*)PluginService::Create<void*>(typ, &description, 2, (
char**)argv);
1188 printout(INFO,
"TestShape",
"+++ Shape verification FAILED. [Plugin not found]");
1189 except(
"TestShape",
"+++ Shape verification FAILED.");
1191 else if ( ::strcmp(result->
GetName(),
"SUCCESS") == 0 ) {
1192 printout(INFO,
"TestShape",
"+++ Shape verification SUCCESSFUL. [type=%s]",name.c_str());
1193 delete result.
ptr();
1196 printout(INFO,
"TestShape",
"+++ Shape verification FAILED [result=%s]",result->
GetName());
1197 printout(INFO,
"TestShape",
"+++ Diagnosis: \n%s",result->
GetTitle());
1198 delete result.
ptr();
1199 except(
"TestShape",
"+++ Shape verification FAILED.");
1215 if ( argc != 2 ) { }
1219 int ref_cr = x_test.hasAttr(
_U(create)) ? x_test.attr<
int>(
_U(create)) : 0;
1220 int nseg = x_test.hasAttr(
_U(segmentation)) ? x_test.attr<
int>(
_U(segmentation)) : -1;
1221 TString ref = x_test.refStr().c_str();
1222 std::string ref_str;
1223 std::stringstream os;
1226 description.manager().SetNsegments(nseg);
1229 for (Int_t ipv=0, npv=
v->GetNdaughters(); ipv < npv; ipv++) {
1231 auto vol = place.
volume();
1232 auto solid = vol.solid();
1233 os <<
"ShapeCheck[" << ipv <<
"] ";
1235 printout(INFO,
"Mesh_Verifier",
"+++ Checking mesh of %s %s [%s] vol:%s.",
1236 solid->IsA()->GetName(),
1237 solid->GetName(), solid->GetTitle(),
1240 gSystem->ExpandPathName(ref);
1242 std::ofstream out(ref, std::fstream::out);
1243 if ( !out.is_open() ) {
1244 except(
"Mesh_Verifier",
"+++ FAILED to open(WRITE) reference file: "+x_test.refStr());
1248 printout(INFO,
"Mesh_Verifier",
"+++ Successfully wrote reference file: "+x_test.refStr());
1250 else if ( ref.Length() > 0 ) {
1252 std::ifstream in(ref.Data(), std::fstream::in);
1253 if ( !in.is_open() ) {
1254 except(
"Mesh_Verifier",
"+++ FAILED to access reference file: "+x_test.refStr());
1259 printout(INFO,
"Mesh_Verifier",
"+++ Successfully read reference file: "+x_test.refStr());
1260 if ( ref_str != os.str() ) {
1261 printout(ERROR,
"Mesh_Verifier",
"+++ Output and reference differ! Please check.");
1262 return Constant(
"FAILURE",os.str().c_str()).
ptr();
1264 printout(INFO,
"Mesh_Verifier",
"+++ Successfully checked CREATED shapes.");
1266 for (Int_t ipv=0, npv=
v->GetNdaughters(); ipv < npv; ipv++) {
1277 else if ( solid->IsA() != TGeoCompositeShape::Class() ) {
1282 printout(INFO,
"Mesh_Verifier",
"+++ Skip re-dimensioning of %s [%s].",
1283 solid->IsA()->GetName(), solid->GetTitle());
1286 for (Int_t ipv=0, npv=
v->GetNdaughters(); ipv < npv; ipv++) {
1288 os <<
"ShapeCheck[" << ipv <<
"] ";
1291 if ( ref_str != os.str() ) {
1292 printout(DEBUG,
"Mesh_Verifier",
"+++ REFERENCE shape mesh:\n%s",ref_str.c_str());
1293 printout(DEBUG,
"Mesh_Verifier",
"+++ REDIMENSIONED shape mesh:\n%s",os.str().c_str());
1294 printout(ERROR,
"Mesh_Verifier",
"+++ Output and reference differ after re-dimension! Please check.");
1295 return Constant(
"FAILURE",os.str().c_str()).
ptr();
1297 printout(INFO,
"Mesh_Verifier",
"+++ Successfully checked REDIMENSIONED shapes.");
1299 return Constant(
"SUCCESS",os.str().c_str()).
ptr();