7 #include <TObjString.h>
15 #include <TPolyLine.h>
18 #include "G4LogicalVolume.hh"
20 #include "G4SystemOfUnits.hh"
21 #include "G4NistManager.hh"
22 #include "G4PVPlacement.hh"
29 #define _IR_REGION_SMARGIN_ ( 50.0 * etm::cm)
30 #define _IR_REGION_BMARGIN_ ( 30.0 * etm::cm)
32 #define _CANVAS_WIDTH_DEFAULT_ ( 1500)
36 #define _COLOR_LEGEND_HEIGHT_ (20.0 * etm::cm)
37 #define _COLOR_LEGEND_STEP_ (80.0 * etm::cm)
38 #define _COLOR_LEGEND_GAP_ ( 5.0 * etm::cm)
41 #define _HALL_RADIAL_BOUNDARY_ (350.0 * etm::cm)
46 #define _SAFETY_CLEARANCE_DEFAULT_ (0.0)
47 #define _VISUAL_CLEARANCE_DEFAULT_ (0.0)
49 #define _CROSSING_ANGLE_DEFAULT_ ( 0.025)
52 #define Printf Printf_opencascade
54 #include <TopoDS_Solid.hxx>
55 #include <BRepPrimAPI_MakeCylinder.hxx>
56 #include <BRep_Builder.hxx>
57 #include <TopoDS_Compound.hxx>
58 #include <TDocStd_Document.hxx>
59 #include <XCAFApp_Application.hxx>
60 #include <XCAFDoc_ShapeTool.hxx>
61 #include <XCAFDoc_ColorTool.hxx>
62 #include <XCAFDoc_DocumentTool.hxx>
63 #include <Quantity_Color.hxx>
64 #include <NCollection_Vector.hxx>
65 #include <STEPCAFControl_Writer.hxx>
67 #include <BRepBuilderAPI_MakePolygon.hxx>
68 #include <BRepBuilderAPI_MakeFace.hxx>
69 #include <BRepPrimAPI_MakeRevol.hxx>
78 mIrRegionLength(length),
79 mIrRegionRadius(radius), mAzimuthalSegmentation(0), mIpOffset(0.0),
81 mXsize(0.0), mYsize(0.0), mX0(0.0), mY0(0.0),
82 mColorLegendEnabled(
true), mZoomedView(
false), mCanvas(0),
89 mG4LogicalWorld(0), mDrawIP6boundaries(
false), mUseDetectorHighlighting(
false)
93 printf(
"\n\n EicToyModel::EicToyModel() -> Singleton instance already exists!\n\n");
110 printf(
"\n\n EicToyModel::Import() -> Singleton instance already exists!\n\n");
118 if (!dynamic_cast<EicToyModel *>(fin.Get(
"EicToyModel"))) {
119 printf(
"Wrong file format (%s): no EicToyModel instance found!\n\n\n", fname);
154 auto air = G4NistManager::Instance()->FindOrBuildMaterial(
"G4_AIR");
158 auto expHall_box =
new G4Box(
"World",
162 auto expHall_log =
new G4LogicalVolume(expHall_box, air,
"World", 0, 0, 0);
164 return new G4PVPlacement(0, G4ThreeVector(), expHall_log,
"World", 0,
false, 0);
166 printf(
"\n\n G4 support is not compiled in; use 'cmake -DGEANT=YES ...' \n\n");
176 for(
auto det: stack->mDetectors)
177 det->PlaceG4Volume(world);
192 bool reset_stacks,
bool redraw)
196 buffer.insert(eta0); buffer.insert(eta1); buffer.insert(eta2); buffer.insert(eta3);
198 if (buffer.size() != 4) {
199 printf(
"At least two of the 'eta' values given to EicToyModel::acceptance() are the same!\n");
204 for(
unsigned bf=0; bf<2; bf++)
206 mEtaLines.erase(stack->EtaBoundary(bf)->GetEta());
208 for(
auto eta: buffer)
218 const char *labels[] = {
"VTX",
"BCK",
"MID",
"FWD"};
219 for(
unsigned st=0; st<4; st++)
242 double dx[2] = {0.0, 0.0};
245 for(
unsigned bf=0; bf<2; bf++) {
250 dx[bf] = vtxarr.size() > 2 ? vtxarr[vtxarr.size()-2].X() : 0.0;
254 auto ll =
EtmLine2D(TVector2(dx[0], 0), TVector2(0,1));
255 auto rr =
EtmLine2D(TVector2(dx[1], 0), TVector2(0,1));
258 if (single && stack != single)
continue;
260 for(
unsigned bf=0; bf<2; bf++) {
261 bool account_crossing_angle = stack ==
fwd() && bf;
264 for(
unsigned vh=0; vh<2; vh++) {
265 for(
unsigned tb=0; tb<2; tb++) {
266 double tbsign = tb ? -1.0 : 1.0;
270 auto lcv =
EtmLine2D(
ip + TVector2( 0,dyv), TVector2(1,0));
271 auto lcm =
EtmLine2D(
ip + TVector2( 0,dym), TVector2(1,0));
274 account_crossing_angle);
276 auto &vtxarr = boundary->mCrackNodes[vh][tb];
279 if (stack ==
vtx() || !dyv ||
280 (stack ==
mid() && bf && !dx[1]) ||
281 (stack ==
bck() && !bf && !dx[0]) ||
282 (stack ==
fwd() && bf && !dx[1]))
283 vtxarr.push_back(ip_native);
286 account_crossing_angle).first;
287 auto arrow =
L -
ip,
n = arrow.Unit();
290 vtxarr.push_back(ip_down);
293 if ((stack ==
bck() && bf) || stack ==
mid() || (stack ==
fwd() && !bf)) {
294 vtxarr.push_back(TVector2(ip.X(), dym));
295 vtxarr.push_back(TVector2(lcm.Cross(l0)));
297 if (stack ==
bck() && !bf) {
298 vtxarr.push_back(TVector2(ip.X(), dyv));
299 vtxarr.push_back(TVector2(lcv.Cross(ll)));
300 vtxarr.push_back(l0.Cross(ll));
302 if (stack ==
fwd() && bf) {
303 vtxarr.push_back(TVector2(ip.X(), dyv));
304 vtxarr.push_back(TVector2(lcv.Cross(
rr)));
305 vtxarr.push_back(l0.Cross(
rr));
313 account_crossing_angle).first);
419 Export((
GetName() + TString(
".root")).Data(), everything, lock);
426 TString str(fname ? TString(fname) :
GetName() + TString(
".vc.gdml"));
428 if (str.EndsWith(
".gdml")) {
432 printf(
"EicToyModel::ExportVacuumChamber() -> vacuum chamber is not defined!\n");
435 printf(
"EicToyModel::ExportVacuumChamber(\"%s\") -> .gdml file extension expected!\n",
446 Handle(TDocStd_Document) outDoc;
447 Handle(XCAFApp_Application) outApp = XCAFApp_Application::GetApplication();
448 outApp->NewDocument(
"ETM", outDoc);
450 Handle (XCAFDoc_ShapeTool) outAssembly = XCAFDoc_DocumentTool::ShapeTool (outDoc->Main());
452 Handle(XCAFDoc_ColorTool) outColors = XCAFDoc_DocumentTool::ColorTool(outDoc->Main());
455 for(
auto shape: shapes) {
456 auto rcolor = shape.first;
459 Quantity_Color ccolor(rcolor->GetRed(), rcolor->GetGreen(), rcolor->GetBlue(), Quantity_TOC_RGB);
460 TDF_Label aLabel = outAssembly->AddShape(*shape.second);
461 outColors->SetColor(aLabel, ccolor, XCAFDoc_ColorSurf);
466 STEPCAFControl_Writer cWriter;
468 cWriter.Transfer(outDoc, STEPControl_ManifoldSolidBrep);
470 cWriter.Write(fname);
473 printf(
"EicToyModel::Export(\"%s\") -> OpenCascade support is not compiled in!\n", fname);
481 std::vector<std::pair<const TColor*, const TopoDS_Shape*> > shapes;
486 for(
auto det: stack->mDetectors) {
487 auto shape = det->BuildCADmodel();
488 shapes.insert(shapes.end(), shape.begin(), shape.end());
501 if (str.EndsWith(
".root")) {
502 TFile fout(str.Data(),
"RECREATE");
523 #if 0//def _OPENCASCADE_
526 const char *qfname =
"/tmp/tmp.stp";
529 std::ifstream fin(qfname);
534 TObjString ostr; ostr.SetString(str);
536 ostr.Write(
"CD.STEP");
545 TObject::Write(
"EicToyModel");
548 }
else if (str.EndsWith(
".stp")) {
551 printf(
"EicToyModel::Export(\"%s\") -> unknown file name extension!\n", fname);
554 printf(
"EicToyModel::Export() -> null pointer given as file name!\n");
591 if (stack !=
vtx() && stack->
etamin() <= eta && eta < stack->etamax())
return stack;
650 mX0 = blX < trX ? blX : trX;
651 mY0 = blY < trY ? blY : trY;
677 unsigned dim = chain.size();
678 std::vector<TVector2> ret;
684 for(
unsigned ivtx=0; ivtx<
dim; ivtx++) {
685 auto const &vcurr0 = chain[ivtx];
691 auto const &vprev0 = chain[ivtx-1];
693 EtmLine2D ll(vcurr0, (vcurr0-vprev0).Unit());
696 ret.push_back(from.
Cross(ll));
698 for(
unsigned jvtx=ivtx; jvtx<
dim; jvtx++) {
699 auto const &vcurr1 = chain[jvtx];
703 ret.push_back(vcurr1);
708 auto const &vprev1 = chain[jvtx-1];
710 EtmLine2D ll(vcurr1, (vcurr1-vprev1).Unit());
711 ret.push_back(to.
Cross(ll));
724 std::pair<std::vector<TVector2>, std::vector<TVector2> >
728 unsigned dim = chain.size();
729 std::pair<std::vector<TVector2>, std::vector<TVector2> > ret;
730 std::vector<TVector2> &before = ret.first, &after = ret.second;
732 for(
unsigned ivtx=0; ivtx<
dim; ivtx++) {
733 auto const &vcurr = chain[ivtx];
738 before.push_back(vcurr);
740 auto const &vprev = chain[ivtx-1];
741 EtmLine2D lcross(vcurr, (vcurr-vprev).Unit());
745 before.push_back(line.
Cross(lcross));
746 after .push_back(line.
Cross(lcross));
747 after .push_back(vcurr);
749 for(
unsigned jvtx=ivtx+1; jvtx<
dim; jvtx++)
750 after.push_back(chain[jvtx]);
769 chain.insert(chain.end(), add.begin(), add.end());
778 std::vector<TVector2> ret;
780 std::pair<std::vector<TVector2>, std::vector<TVector2> >
cm =
GetIntersection(chain, am);
781 std::pair<std::vector<TVector2>, std::vector<TVector2> > cp =
GetIntersection(chain, ap);
782 std::pair<std::vector<TVector2>, std::vector<TVector2> > cc =
GetIntersection(chain, cut);
786 const TVector2 &
C = cc.second[0];
790 const TVector2 &
L = chain[chain.size()-1];
791 const TVector2 &P = cut.
Cross(am), &Q = cut.
Cross(ap);
793 bool vcut = fabs(cut.
V().X()) < fabs(cut.
V().Y());
794 TVector2 D = TVector2(vcut ? Q.X() : L.X(), vcut ? L.Y() : Q.Y());
796 if (dcm <= 0.0 && dcp < 0.0) {
815 }
else if (dcm > 0.0 && dcp < 0.0) {
870 auto hstack = request->mHostDetector->mStack;
871 if (single && hstack != single)
continue;
873 auto rstack = request->mReferenceDetector->mStack;
874 auto host = request->mHostDetector, ref = request->mReferenceDetector;
878 bool order = rstack->EtaBoundary(0)->GetEta() > hstack->EtaBoundary(0)->GetEta();
880 hstack->EtaBoundary( order),
889 for(
unsigned vh=0; vh<2; vh++) {
890 for(
unsigned tb=0; tb<2; tb++) {
891 double dthost = host->GetActualDistance();
892 double dtref = (ref && !ref->IsDummy()? ref->GetActualDistance() - ref->length()/2 : 0.0) +
893 request->mTransverseOffset;
895 TVector2 aaxis(hstack->mAlignmentAxis.X(), (tb ? -1.0 : 1.0)*hstack->mAlignmentAxis.Y());
896 TVector2 caxis(rstack->mAlignmentAxis.X(), (tb ? -1.0 : 1.0)*rstack->mAlignmentAxis.Y());
901 auto am =
EtmLine2D(
ip + (dthost - host->length()/2 )*aaxis,
902 aaxis.Rotate(-
M_PI/2));
903 auto ap =
EtmLine2D(
ip + (dthost + host->length()/2 )*aaxis,
904 aaxis.Rotate(-
M_PI/2));
906 caxis.Rotate(-
M_PI/2));
910 bool central = host->mStack ==
vtx() || host->mStack ==
mid();
917 for(
unsigned bf=0; bf<2; bf++) {
918 auto boundary = boundaries[bf];
919 if (!boundary)
continue;
923 vtxarr =
RebuildCrack(vtxarr, am, ap, cut, request->mStretch);
937 for(
auto det:
bck()->mDetectors)
940 for(
auto det:
mid()->mDetectors)
943 for(
auto det:
fwd()->mDetectors)
952 for(
auto boundary: mEtaBoundaries)
953 for(
unsigned vh=0; vh<2; vh++) {
954 auto &wdarr = boundary->mCrackWidths[vh];
959 for(
unsigned iq=0; iq<boundary->mCrackNodes[vh][0].size()-1; iq++)
960 wdarr.push_back(SafetyClearance());
978 gStyle->SetCanvasColor(0);
997 stack->CalculateActualDistances();
1013 for(
auto stack: mStacks)
1021 for (
unsigned tb=0; tb<2; tb++) {
1026 for(
auto det: stack->mDetectors)
1029 if (det->Polygons().size())
1030 det->DrawPolygon(det->Polygons()[vh*2+tb]);
1063 TVector2 coord =
cnv(where);
1067 auto text =
new TLatex(coord.X(), coord.Y(), what);
1069 text->SetTextAlign(22);
1070 text->SetTextColor(color);
1071 text->SetTextFont(43);
1081 double xxc[dim+1], yyc[dim+1];
1083 for(
unsigned iq=0; iq<
dim; iq++) {
1084 auto xyc =
cnv(TVector2(xx[iq], yy[iq]));
1085 xxc[iq] = xyc.X(); yyc[iq] = xyc.Y();
1087 xxc[
dim] = xxc[0]; yyc[
dim] = yyc[0];
1090 TPolyLine *
poly =
new TPolyLine(dim+1, xxc, yyc);
1092 poly->SetLineColor(kBlack);
1093 poly->SetFillColor(color);
1094 poly->SetLineWidth(1);
1097 if (line) poly->Draw();
1104 double xx[4] = {bl.X(), tr.X(), tr.X(), bl.X()};
1105 double yy[4] = {bl.Y(), bl.Y(), tr.Y(), tr.Y()};
1115 TVector2 p1 =
cnv(from), p2 =
cnv(to);
1116 double xx[2] = {p1.X(), p2.X()}, yy[2] = {p1.Y(), p2.Y()};
1119 TPolyLine *
poly =
new TPolyLine(2, xx, yy);
1121 poly->SetLineColor(color);
1122 poly->SetLineWidth(width);
1123 poly->SetLineStyle(style);
1131 bool account_crossing_angle)
1135 if (eta > 0.0 && vh && account_crossing_angle) theta += tbsign*
mCrossingAngle;
1137 TVector2 dxy = 1E-6*TVector2(1,0).Rotate(theta);
1144 bool account_crossing_angle)
1148 if (eta > 0.0 && vh && account_crossing_angle) theta += tbsign*
mCrossingAngle;
1152 double x0 = (theta < TMath::Pi()/2 ? 1.0 : -1.0)*
dx;
1153 double y0 = (x0 -
mIpOffset)*tan(theta);
1156 return std::make_pair(TVector2(x0, tbsign*y0),
true);
1166 std::pair<bool, bool> what,
bool side)
const
1173 TString label; label.Form(
"#eta %4.2f", eta);
1176 double sign = to.Y() > 0.0 ? 1.0 : -1.0;
1177 WriteText(to + TVector2(!side ? 0.0 : (eta < 0.0 ? -22.0 : 22.0),
1178 !side ? sign*7.0*
etm::cm : 0.0), label);
1187 for(
unsigned tb=0; tb<2; tb++) {
1208 for(
unsigned tb=0; tb<2; tb++) {
1212 if (stack ==
vtx())
continue;
1214 for(
unsigned im=0; im<2; im++) {
1215 auto boundary = stack->EtaBoundary(im);
1216 const auto &vtxarr = boundary->mCrackNodes[vh][tb];
1218 for(
unsigned ivtx=1; ivtx<vtxarr.size(); ivtx++)
1240 WriteText(TVector2(-300.0, 365.0),
"R = 375 cm", kRed);
1249 WriteText(TVector2(-300.0, 400.0),
"R = 410 cm", kBlue);
1257 for(
unsigned tb=0; tb<2; tb++) {
1275 for(
unsigned fb=0; fb<2; fb++) {
1276 auto stack = stacks[fb];
1279 if (!
marker->IsDummy()) {
1281 TVector2 from =
cnv(spot - TVector2(0.0, 10 *
etm::cm)), to =
cnv(spot);
1284 auto arrow =
new TArrow(from.X(), from.Y(), to.X(), to.Y(), 0.005,
"|>");
1285 arrow->SetLineWidth(1);
1286 arrow->SetLineColor(kRed);
1292 double alength = 30.0 *
etm::cm;
1294 for(
unsigned lr=0; lr<2; lr++) {
1298 TVector2 from =
cnv(TVector2(
mIpOffset + (lr ? 1.0 : -1.0)*alength, 0.0));
1301 auto arrow =
new TArrow(from.X(), from.Y(), to.X(), to.Y(), 0.007,
"|>");
1302 arrow->SetLineWidth(2);
1303 arrow->SetLineColor(lr ? kBlue : kRed);
1318 if (stack && (stack ==
fwd() || stack ==
bck())) {
1322 if (!
marker->IsDummy()) {
1323 double sign = (
eta < 0.0 ? -1 : 1);
1327 double zmax = zmarker, rstep = 5 *
etm::cm;
1329 double rmax = fabs(
dz*tan(theta));
1331 for(
unsigned tb=0; tb<2; tb++) {
1334 for(
unsigned iq=0; (iq+0)*rstep < rmax; iq++) {
1336 double y0 = (tb ? -1.0 : 1.0)*iq*rstep;
1338 from = TVector2(
GetIpLocation().X() + iq*rstep/tan(theta), y0), to = TVector2(zmax, y0);
1343 TVector2 apex(zmax, (tb ? -1.0 : 1.0)*rmax);
1359 for(
unsigned iq=0; iq<
dim; iq++) {
1360 double zOffset = step*(iq - (dim-1)/2.);
1368 TVector2 from(zOffset, lift + dlift), to(zOffset, ((iq%2) ? -10.0 : -5.0) *
etm::cm + lift + dlift);
1376 label.Form(
"%c%5.1f", zOffset > 0.0 ?
'+' :
'-', fabs(zOffset));
1385 for(
unsigned tb=0; tb<2; tb++) {
1388 double tbsign = tb ? -1.0 : 1.0;
1390 for(
unsigned lr=0; lr<2; lr++) {
1395 for(
unsigned iq=0; iq<
dim; iq++) {
1396 double yOffset = step*iq;
1398 if (yOffset > mIrRegionRadius)
continue;
1400 TVector2 from(z0, tbsign*yOffset), to(z0 + lrsign*((iq%2) ? 5.0 : 10.0), tbsign*yOffset);
1412 if (!rows) rows = 1;
1415 std::map<TString, int>
legend;
1419 for(
auto det: stack->mDetectors)
1423 det->RegisterFillColor(legend);
1426 unsigned counter = 0;
1428 double zOffset =
mX0 + _COLOR_LEGEND_HEIGHT_ + step/2;
1429 for(
auto label: legend) {
1430 int color = label.second;
1433 unsigned Xjump = rows == 1 ? 1 : counter%rows, Yjump = rows == 1 ? 0 : counter%rows;
1436 TVector2 bl(zOffset - step/2 +
_COLOR_LEGEND_GAP_/2, yOffset - _COLOR_LEGEND_HEIGHT_/2);
1437 TVector2 tr(zOffset + step/2 -
_COLOR_LEGEND_GAP_/2, yOffset + _COLOR_LEGEND_HEIGHT_/2);
1440 WriteText(TVector2(zOffset, yOffset), label.first.Data(),
1442 (color == kBlack || color == kBlue+1 || color == kAzure+4 || color == kViolet+1) ? kWhite : kBlack);
1444 zOffset += Xjump*
step; counter++;