19 #include <TGeoScaledShape.h>
20 #include <TGeoShapeAssembly.h>
47 Solid solid =
Scale(shape.ptr(), scale.x(1.0), scale.y(1.0), scale.z(1.0));
48 if ( e.
hasAttr(
_U(name)) ) solid->SetName(e.
attr<std::string>(
_U(name)).c_str());
68 if ( e.
hasAttr(
_U(name)) ) solid->SetName(e.
attr<std::string>(
_U(name)).c_str());
87 Solid solid =
Box(dim.dx(),dim.dy(),dim.dz());
88 if ( e.
hasAttr(
_U(name)) ) solid->SetName(e.
attr<std::string>(
_U(name)).c_str());
111 double p[3] = { point.x(), point.y(), point.z()};
112 double n[3] = { normal.x(), normal.y(), normal.z()};
114 if ( e.
hasAttr(
_U(name)) ) solid->SetName(e.
attr<std::string>(
_U(name)).c_str());
133 double rmi1 = e.rmin1(0.0), rma1 = e.rmax1();
134 Solid solid =
Cone(e.z(0.0), rmi1, rma1, e.rmin2(rmi1), e.rmax2(rma1));
135 if ( e.
hasAttr(
_U(name)) ) solid->SetName(e.
attr<std::string>(
_U(name)).c_str());
160 std::vector<double> rmin,rmax,z;
161 double start = e.startphi(0e0), deltaphi = e.deltaphi(2*
M_PI);
164 rmin.emplace_back(plane.rmin(0.0));
165 rmax.emplace_back(plane.rmax());
166 z.emplace_back(plane.z());
169 throw std::runtime_error(
"PolyCone Shape> Not enough Z planes. minimum is 2!");
172 if ( e.
hasAttr(
_U(name)) ) solid->SetName(e.
attr<std::string>(
_U(name)).c_str());
203 if ( aphi || bphi ) {
204 double phi1 = e.phi1(0.0);
205 double phi2 = e.phi2(2*
M_PI);
207 solid =
ConeSegment(e.dz(),e.rmin1(0.0),e.rmax1(),e.rmin2(0.0),e.rmax2(),phi1,phi2);
210 double start_phi = e.startphi(0.0);
211 double delta_phi = e.deltaphi(2*
M_PI);
212 while ( start_phi > 2.0*
M_PI ) start_phi -= 2.0*
M_PI;
214 solid =
ConeSegment(e.dz(),e.rmin1(0.0),e.rmax1(),e.rmin2(0.0),e.rmax2(),start_phi,start_phi+delta_phi);
216 if ( e.
hasAttr(
_U(name)) ) solid->SetName(e.
attr<std::string>(
_U(name)).c_str());
247 if ( aphi || bphi ) {
248 double phi1 = e.phi1(0.0);
249 double phi2 = e.phi2(2*
M_PI);
250 solid =
Tube(e.rmin(0.0),e.rmax(),e.dz(0.0),phi1, phi2);
253 double phi1 = e.startphi(0.0);
254 double phi2 = phi1 + e.deltaphi(2*
M_PI);
255 solid =
Tube(e.rmin(0.0),e.rmax(),e.dz(0.0),phi1,phi2);
257 if ( e.
hasAttr(
_U(name)) ) solid->SetName(e.
attr<std::string>(
_U(name)).c_str());
272 double zpos = 0.0, zneg = 0.0;
274 nseg = e.nsegments();
277 zneg = -1.0*(zpos = e.dz());
283 solid =
TwistedTube(e.twist(0.0), e.rmin(0.0),e.rmax(),zneg, zpos, nseg, e.deltaphi(2*
M_PI));
285 if ( e.
hasAttr(
_U(name)) ) solid->SetName(e.
attr<std::string>(
_U(name)).c_str());
307 if ( e.
hasAttr(
_U(name)) ) solid->SetName(e.
attr<std::string>(
_U(name)).c_str());
321 if ( e.
hasAttr(
_U(name)) ) solid->SetName(e.
attr<std::string>(
_U(name)).c_str());
334 double sp = e.startphi(0.0), dp = e.deltaphi(2*
M_PI);
339 if ( e.
hasAttr(
_U(name)) ) solid->SetName(e.
attr<std::string>(
_U(name)).c_str());
378 solid =
Trap(e.z(0.0),e.theta(0),e.phi(0),y1,x1,x2,e.alpha1(0),y2,x3,x4,e.alpha2(0));
380 if ( e.
hasAttr(
_U(name)) ) solid->SetName(e.
attr<std::string>(
_U(name)).c_str());
394 if ( e.
hasAttr(
_U(name)) ) solid->SetName(e.
attr<std::string>(
_U(name)).c_str());
412 Solid solid =
Trd1(e.x1(),e.x2(),e.y(),e.z(0.0));
413 if ( e.
hasAttr(
_U(name)) ) solid->SetName(e.
attr<std::string>(
_U(name)).c_str());
431 Solid solid =
Trd2(e.x1(),e.x2(),e.y1(),e.y2(),e.z(0.0));
432 if ( e.
hasAttr(
_U(name)) ) solid->SetName(e.
attr<std::string>(
_U(name)).c_str());
461 if ( aphi || bphi ) {
462 double phi1 = e.phi1(0.0);
463 double phi2 = e.phi2(2*
M_PI);
465 solid =
Torus(e.r(), e.rmin(0.0), e.rmax(), phi1, phi2-phi1);
468 double start_phi = e.startphi(0.0);
469 double delta_phi = e.deltaphi(2*
M_PI);
470 while ( start_phi > 2.0*
M_PI ) start_phi -= 2.0*
M_PI;
472 solid =
Torus(e.r(), e.rmin(0.0), e.rmax(), start_phi, delta_phi);
474 if ( e.
hasAttr(
_U(name)) ) solid->SetName(e.
attr<std::string>(
_U(name)).c_str());
496 double startphi = e.phi(0e0);
497 double endphi = startphi + 2.*
M_PI;
498 double starttheta = e.theta(0e0);
499 double endtheta = starttheta +
M_PI;
502 startphi = e.startphi();
503 endphi = startphi + 2.*
M_PI;
508 endphi = startphi + e.deltaphi();
511 starttheta = e.starttheta();
512 endtheta = starttheta +
M_PI;
515 endtheta = e.endtheta();
517 endtheta = starttheta + e.deltatheta();
519 Solid solid =
Sphere(e.rmin(0e0), e.rmax(), starttheta, endtheta, startphi, endphi);
520 if ( e.
hasAttr(
_U(name)) ) solid->SetName(e.
attr<std::string>(
_U(name)).c_str());
539 if ( e.
hasAttr(
_U(name)) ) solid->SetName(e.
attr<std::string>(
_U(name)).c_str());
559 Solid solid =
Hyperboloid(e.rmin(), e.inner_stereo(), e.rmax(), e.outer_stereo(), e.dz());
560 if ( e.
hasAttr(
_U(name)) ) solid->SetName(e.
attr<std::string>(
_U(name)).c_str());
580 if ( e.
hasAttr(
_U(name)) ) solid->SetName(e.
attr<std::string>(
_U(name)).c_str());
601 std::vector<double> z, rmin, rmax;
604 rmin.emplace_back(plane.rmin());
605 rmax.emplace_back(plane.rmax());
606 z.emplace_back(plane.z());
608 Solid solid =
Polyhedra(e.numsides(),e.startphi(),e.deltaphi(),z,rmin,rmax);
609 if ( e.
hasAttr(
_U(name)) ) solid->SetName(e.
attr<std::string>(
_U(name)).c_str());
622 std::vector<double> pt_x, pt_y, sec_z, sec_x, sec_y, sec_scale;
623 for (
xml_coll_t sec(element,
_U(section)); sec; ++sec ) {
625 sec_z.emplace_back(section.attr<
double>(
_U(z)));
626 sec_x.emplace_back(section.attr<
double>(
_U(x)));
627 sec_y.emplace_back(section.attr<
double>(
_U(y)));
628 sec_scale.emplace_back(section.attr<
double>(
_U(scale),1.0));
632 pt_x.emplace_back(point.attr<
double>(
_U(x)));
633 pt_y.emplace_back(point.attr<
double>(
_U(y)));
636 if ( e.
hasAttr(
_U(name)) ) solid->SetName(e.
attr<std::string>(
_U(name)).c_str());
651 memset(&
v[0][0],0,
sizeof(
v));
658 if ( e.
hasAttr(
_U(name)) ) solid->SetName(e.
attr<std::string>(
_U(name)).c_str());
671 std::vector<TessellatedSolid::Vertex> vertices;
674 vertices.emplace_back(
v.x(),
v.y(),
v.z());
677 for (
xml_coll_t facet(element,
_U(facet)); facet; ++facet ) ++num_facets;
679 if ( e.
hasAttr(
_U(name)) ) solid->SetName(e.
attr<std::string>(
_U(name)).c_str());
680 for (
xml_coll_t facet(element,
_U(facet)); facet; ++facet ) {
682 size_t i0 = f.attr<
size_t>(
_U(v0));
683 size_t i1 = f.attr<
size_t>(
_U(v1));
684 size_t i2 = f.attr<
size_t>(
_U(v2));
685 if ( f.hasAttr(
_U(v3)) ) {
686 size_t i3 = f.attr<
size_t>(
_U(v3));
687 solid.
addFacet(vertices[i0], vertices[i1], vertices[i2], vertices[i3]);
690 solid.
addFacet(vertices[i0], vertices[i1], vertices[i2]);
720 std::string op = e.
attr<std::string>(
_U(operation)) ;
721 std::transform( op.begin(), op.end(), op.begin(), ::tolower);
725 bool useRot(
false), usePos(
false), useTrans(
false);
735 pos =
Position( x_pos.x(0.0),x_pos.y(0.0),x_pos.z(0.0) );
740 rot =
RotationZYX( x_rot.z(0.0),x_rot.y(0.0),x_rot.x(0.0) ) ;
743 if( op ==
"subtraction" ) {
748 else if( useRot && usePos ) {
758 else if( op ==
"union" ) {
763 else if( useRot && usePos )
766 resultSolid =
UnionSolid(solid1, solid2, rot);
768 resultSolid =
UnionSolid(solid1, solid2, pos);
772 else if( op ==
"intersection" ) {
777 else if( useRot && usePos )
788 throw std::runtime_error(std::string(
" create_BooleanShape - unknown operation given: ") + op +
789 std::string(
" - needs to be one of 'subtraction','union' or 'intersection' ") ) ;
791 Solid solid = resultSolid ;
792 if ( e.
hasAttr(
_U(name)) ) solid->SetName(e.
attr<std::string>(
_U(name)).c_str());
801 Solid tmp, solid, result;
806 std::string op = e.
attr<std::string>(
_U(operation)) ;
807 std::transform( op.begin(), op.end(), op.begin(), ::tolower);
811 std::string tag = x_elt.tag();
812 if ( tag ==
"shape" && !result.
isValid() ) {
814 if ( (attr=i.attr_nothrow(
_U(name))) ) result->SetName(i.attr<std::string>(attr).c_str());
817 else if ( tag ==
"shape" && !solid.
isValid() ) {
819 if ( (attr=i.attr_nothrow(
_U(name))) ) result->SetName(i.attr<std::string>(attr).c_str());
823 if ( tag ==
"position" ) {
824 if ( flag == 4 ) trafo = position * trafo;
825 else if ( flag == 5 ) trafo = (position * rotation) * trafo;
826 Position pos(x_elt.x(0), x_elt.y(0), x_elt.z(0));
831 else if ( tag ==
"positionRZPhi" ) {
832 if ( flag == 4 ) trafo = position * trafo;
833 else if ( flag == 5 ) trafo = (position * rotation) * trafo;
834 ROOT::Math::RhoZPhiVector pos(x_elt.r(0), x_elt.z(0), x_elt.phi(0));
839 else if ( tag ==
"transformation" ) {
840 if ( flag == 4 ) trafo = position * trafo;
841 else if ( flag == 5 ) trafo = (position * rotation) * trafo;
847 else if ( tag ==
"rotation" ) {
851 else if ( tag ==
"shape" ) {
853 if ( flag == 4 ) trafo = position * trafo;
854 else if ( flag == 5 ) trafo = (position * rotation) * trafo;
856 if( op ==
"subtraction" )
858 else if( op ==
"union" )
860 else if( op ==
"intersection" )
863 throw std::runtime_error(
" create_BooleanShape - unknown operation given: " + op +
864 " - needs to be one of 'subtraction','union' or 'intersection' ");
869 if ( (attr=i.attr_nothrow(
_U(name))) ) result->SetName(i.attr<std::string>(attr).c_str());
876 if ( flag == 4 ) trafo = position * trafo;
877 else if ( flag == 5 ) trafo = (position * rotation) * trafo;
878 if( op ==
"subtraction" )
880 else if( op ==
"union" )
882 else if( op ==
"intersection" )
885 throw std::runtime_error(
" create_BooleanShape - unknown operation given: " + op +
886 " - needs to be one of 'subtraction','union' or 'intersection' ");
892 std::string nam = element.
attr<std::string>(attr);
893 result->SetName(nam.c_str());
920 std::string typ = elt.
attr<std::string>(
_U(type));
927 iRot.GetComponents(elements);
929 r.SetMatrix(elements);
930 TGeoTranslation t(iTrans.x(), iTrans.y(), iTrans.z());
931 return new TGeoCombiTrans(t, r);
942 std::string name = x_det.nameStr();
950 printout(DEBUG,
"TestShape",
"+++ Create shape: %s build type is: %s",
952 if ( x_det.hasChild(
_U(material)) ) {
953 mat = description.
material(x_det.child(
_U(material)).attr<std::string>(
_U(name)));
954 printout(INFO,
"TestShape",
"+++ Volume material is %s", mat.
name());
956 for (
xml_coll_t itm(e,
_U(check)); itm; ++itm, ++count ) {
959 xml_dim_t pos (x_check.child(
_U(position),
false));
960 xml_dim_t rot (x_check.child(
_U(rotation),
false));
961 bool reflect = x_check.hasChild(
_U(reflect));
962 bool reflectZ = x_check.hasChild(
_U(reflect_z));
963 bool reflectY = x_check.hasChild(
_U(reflect_y));
964 bool reflectX = x_check.hasChild(
_U(reflect_x));
965 std::string shape_type = shape.typeStr();
969 if ( shape_type ==
"CAD_Assembly" || shape_type ==
"CAD_MultiVolume" ) {
971 solid = volume->GetShape();
973 else if ( shape_type ==
"StdVolume" ) {
975 solid = volume->GetShape();
977 else if ( shape_type ==
"GenVolume" ) {
979 solid = volume->GetShape();
985 if ( x_det.hasChild(
_U(sensitive)) ) {
986 std::string sens_type = x_det.child(
_U(sensitive)).attr<std::string>(
_U(type));
989 printout(INFO,
"TestShape",
"+++ Sensitive type is %s", sens_type.c_str());
992 solid->SetName(shape_type.c_str());
995 if ( pos.ptr() && rot.ptr() ) {
997 Position pos3D(pos.x(0),pos.y(0),pos.z(0));
1000 else if ( pos.ptr() ) {
1003 else if ( rot.ptr() ) {
1009 tr = tr *
Rotation3D(1., 0., 0., 0., 1., 0., 0., 0., -1.);
1012 tr = tr *
Rotation3D(-1.,0.,0.,0.,1.,0.,0.,0.,1.);
1015 tr = tr *
Rotation3D(1.,0.,0.,0.,-1.,0.,0.,0.,1.);
1018 tr = tr *
Rotation3D(1.,0.,0.,0.,1.,0.,0.,0.,-1.);
1020 pv = assembly.placeVolume(volume,tr);
1022 if ( x_check.hasAttr(
_U(
id)) ) {
1024 printout(INFO,
"TestShape",
"+++ Volume id is %d", x_check.id());
1026 const char* nam = solid->GetName();
1027 printout(INFO,
"TestShape",
"Created successfull shape of type: %s %c%s%c",
1028 shape_type.c_str(), nam ?
'[' :
' ', nam ? nam :
"" ,nam ?
']' :
' ');
1030 bool instance_test =
false;
1031 if ( shape_type ==
"CAD_Assembly" || shape_type ==
"CAD_MultiVolume" ) {
1032 solid->SetTitle(shape_type.c_str());
1033 instance_test =
true;
1035 else if ( 0 == strcasecmp(solid->GetTitle(),
BOX_TAG) )
1037 else if ( 0 == strcasecmp(solid->GetTitle(),
TUBE_TAG) )
1039 else if ( 0 == strcasecmp(solid->GetTitle(),
CUTTUBE_TAG) )
1041 else if ( 0 == strcasecmp(solid->GetTitle(),
CONE_TAG) )
1043 else if ( 0 == strcasecmp(solid->GetTitle(),
TRD1_TAG) )
1045 else if ( 0 == strcasecmp(solid->GetTitle(),
TRD2_TAG) )
1047 else if ( 0 == strcasecmp(solid->GetTitle(),
TORUS_TAG) )
1049 else if ( 0 == strcasecmp(solid->GetTitle(),
SPHERE_TAG) )
1051 else if ( 0 == strcasecmp(solid->GetTitle(),
HALFSPACE_TAG) )
1059 else if ( 0 == strcasecmp(solid->GetTitle(),
"PolyhedraRegular") )
1061 else if ( 0 == strcasecmp(solid->GetTitle(),
POLYHEDRA_TAG) )
1067 else if ( 0 == strcasecmp(solid->GetTitle(),
SCALE_TAG) )
1073 else if ( 0 == strcasecmp(solid->GetTitle(),
POLYCONE_TAG) )
1087 else if ( 0 == strcasecmp(solid->GetTitle(),
TRAP_TAG) ) {
1101 else if ( 0 == strcasecmp(solid->GetTitle(),
UNION_TAG) ) {
1136 if ( !instance_test || ::strcasecmp(shape_type.c_str(),solid->GetTitle()) != 0 ) {
1137 printout(ERROR,
"TestShape",
"BAD shape type: %s <-> %s Instance test: %s",
1138 shape_type.c_str(), solid->GetTitle(),
1139 instance_test ?
"OK" :
"FAILED");
1142 printout(INFO,
"TestShape",
"Correct shape type: %s %s <-> %s Instance test: %s",
1143 solid->GetName(), shape_type.c_str(), solid->GetTitle(),
"OK");
1147 xml_dim_t x_pos(x_reflect.child(
_U(position),
false));
1148 xml_dim_t x_rot(x_reflect.child(
_U(rotation),
false));
1149 DetElement full_detector(name+
"_full",100+x_det.id());
1150 Assembly full_assembly(name+
"_full");
1154 if ( x_rot ) refl_rot =
RotationZYX(x_rot.z(0),x_rot.y(0),x_rot.x(0));
1155 if ( x_pos ) refl_pos =
Position(x_pos.x(0),x_pos.y(0),x_pos.z(0));
1159 pv = full_assembly.placeVolume(assembly);
1160 full_detector.add(
det);
1161 det.setPlacement(pv);
1164 auto reflected =
det.reflect(name+
"_reflected",100+x_det.id());
1165 pv = full_assembly.placeVolume(reflected.second, refl_trafo);
1166 full_detector.add(reflected.first);
1167 reflected.first.setPlacement(pv);
1171 full_detector.setPlacement(pv);
1173 det = full_detector;
1178 det.setPlacement(pv);
1183 std::string typ = x_test.typeStr();
1184 const void* argv[] = { &e, &pv, 0};
1185 Ref_t result = (
NamedObject*)PluginService::Create<void*>(typ, &description, 2, (
char**)argv);
1187 printout(INFO,
"TestShape",
"+++ Shape verification FAILED. [Plugin not found]");
1188 except(
"TestShape",
"+++ Shape verification FAILED.");
1190 else if ( ::strcmp(result->
GetName(),
"SUCCESS") == 0 ) {
1191 printout(INFO,
"TestShape",
"+++ Shape verification SUCCESSFUL. [type=%s]",name.c_str());
1192 delete result.
ptr();
1195 printout(INFO,
"TestShape",
"+++ Shape verification FAILED [result=%s]",result->
GetName());
1196 printout(INFO,
"TestShape",
"+++ Diagnosis: \n%s",result->
GetTitle());
1197 delete result.
ptr();
1198 except(
"TestShape",
"+++ Shape verification FAILED.");
1214 if ( argc != 2 ) { }
1218 int ref_cr = x_test.hasAttr(
_U(create)) ? x_test.attr<
int>(
_U(create)) : 0;
1219 int nseg = x_test.hasAttr(
_U(segmentation)) ? x_test.attr<
int>(
_U(segmentation)) : -1;
1220 TString ref = x_test.refStr().c_str();
1221 std::string ref_str;
1222 std::stringstream os;
1225 description.manager().SetNsegments(nseg);
1228 for (Int_t ipv=0, npv=
v->GetNdaughters(); ipv < npv; ipv++) {
1230 auto vol = place.
volume();
1231 auto solid = vol.solid();
1232 os <<
"ShapeCheck[" << ipv <<
"] ";
1234 printout(INFO,
"Mesh_Verifier",
"+++ Checking mesh of %s %s [%s] vol:%s.",
1235 solid->IsA()->GetName(),
1236 solid->GetName(), solid->GetTitle(),
1239 gSystem->ExpandPathName(ref);
1241 std::ofstream out(ref, std::fstream::out);
1242 if ( !out.is_open() ) {
1243 except(
"Mesh_Verifier",
"+++ FAILED to open(WRITE) reference file: "+x_test.refStr());
1247 printout(INFO,
"Mesh_Verifier",
"+++ Successfully wrote reference file: "+x_test.refStr());
1249 else if ( ref.Length() > 0 ) {
1251 std::ifstream in(ref.Data(), std::fstream::in);
1252 if ( !in.is_open() ) {
1253 except(
"Mesh_Verifier",
"+++ FAILED to access reference file: "+x_test.refStr());
1258 printout(INFO,
"Mesh_Verifier",
"+++ Successfully read reference file: "+x_test.refStr());
1259 if ( ref_str != os.str() ) {
1260 printout(ERROR,
"Mesh_Verifier",
"+++ Output and reference differ! Please check.");
1261 return Constant(
"FAILURE",os.str().c_str()).
ptr();
1263 printout(INFO,
"Mesh_Verifier",
"+++ Successfully checked CREATED shapes.");
1265 for (Int_t ipv=0, npv=
v->GetNdaughters(); ipv < npv; ipv++) {
1276 else if ( solid->IsA() != TGeoCompositeShape::Class() ) {
1281 printout(INFO,
"Mesh_Verifier",
"+++ Skip re-dimensioning of %s [%s].",
1282 solid->IsA()->GetName(), solid->GetTitle());
1285 for (Int_t ipv=0, npv=
v->GetNdaughters(); ipv < npv; ipv++) {
1287 os <<
"ShapeCheck[" << ipv <<
"] ";
1290 if ( ref_str != os.str() ) {
1291 printout(DEBUG,
"Mesh_Verifier",
"+++ REFERENCE shape mesh:\n%s",ref_str.c_str());
1292 printout(DEBUG,
"Mesh_Verifier",
"+++ REDIMENSIONED shape mesh:\n%s",os.str().c_str());
1293 printout(ERROR,
"Mesh_Verifier",
"+++ Output and reference differ after re-dimension! Please check.");
1294 return Constant(
"FAILURE",os.str().c_str()).
ptr();
1296 printout(INFO,
"Mesh_Verifier",
"+++ Successfully checked REDIMENSIONED shapes.");
1298 return Constant(
"SUCCESS",os.str().c_str()).
ptr();