Line data Source code
1 : /**************************************************************************
2 : * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3 : * *
4 : * Author: The ALICE Off-line Project. *
5 : * Contributors are mentioned in the code where appropriate. *
6 : * *
7 : * Permission to use, copy, modify and distribute this software and its *
8 : * documentation strictly for non-commercial purposes is hereby granted *
9 : * without fee, provided that the above copyright notice appears in all *
10 : * copies and that both the copyright notice and this permission notice *
11 : * appear in the supporting documentation. The authors make no claims *
12 : * about the suitability of this software for any purpose. It is *
13 : * provided "as is" without express or implied warranty. *
14 : **************************************************************************/
15 :
16 :
17 :
18 : // General Root includes
19 : //#include <Riostream.h>
20 : #include <TMath.h>
21 : #include <TVectorD.h>
22 :
23 : // Root Geometry includes
24 : #include <TGeoManager.h>
25 : #include <TGeoVolume.h>
26 : #include <TGeoTube.h>
27 : #include <TGeoTorus.h>
28 : #include <TGeoMatrix.h>
29 :
30 : #include "AliITSv11GeomCableRound.h"
31 :
32 : //*************************************************************************
33 : // Class for round cables
34 : //
35 : // Ludovic Gaudichet gaudichet@to.infn.it
36 : //*************************************************************************
37 :
38 : /*
39 : // ************************************************************************
40 : // Here is a example on how to use this class
41 : // ************************************************************************
42 :
43 : // Getting some media
44 : TGeoMedium *air = gGeoManager->GetMedium("ITS_AIR$");
45 : TGeoMedium *water = gGeoManager->GetMedium("ITS_WATER");
46 : TGeoMedium *alu = gGeoManager->GetMedium("ITS_ITSal");
47 :
48 : // Creating a small box inside a bigger one (containers)
49 : TGeoBBox *box1 = new TGeoBBox("box1", 6,10,10);
50 : TGeoBBox *bigBox = new TGeoBBox("bigBox", 20,10,10);
51 : TGeoVolume *vbox1 = new TGeoVolume("vbox1", box1, air);
52 : TGeoVolume *vBigBox = new TGeoVolume("vBigBox", bigBox, air);
53 : vbox1->SetVisibility(kFALSE);
54 : vBigBox->SetVisibility(kFALSE);
55 :
56 : TGeoTranslation *tr1 = new TGeoTranslation("negTr",-14,0,0);
57 : vBigBox->AddNode(vbox1, 1, tr1);
58 : moth->AddNode(vBigBox, 1, 0);
59 :
60 : // **************************************************
61 : // Inserting a round cable (or here a water pipe...)
62 : // **************************************************
63 :
64 : Int_t waterColor = 7;
65 : Int_t aluColor = 5;
66 : AliITSv11GeomCableRound roundCable("waterPipe", 0.9); //radius of 0.9cm
67 : roundCable.SetNLayers(2);
68 : roundCable.SetLayer(0, 0.7, water, waterColor); // radius of 0.7cm
69 : roundCable.SetLayer(1, 0.2, alu, aluColor); // thickness of 0.2cm
70 :
71 : // ****** Set check points and their containers ******
72 : // The 2 first points are in the small box (vbox1)
73 : // The second point is at the boundary
74 :
75 : Double_t coord0[3] = {0,-2,-2};
76 : Double_t coord1[3] = {6,2,1};
77 : Double_t vect0[3] = {1,1,0};
78 : Double_t vect1[3] = {1,0,0};
79 : // coordinates have to be given in the specified container
80 : // reference system (here it's going to be vbox1).
81 : // vect1 and vect2 are vectors perpendicular to the segment ends
82 : // (These vectors don't need to be normalized)
83 : roundCable.AddCheckPoint( vbox1, 0, coord0, vect0);
84 : roundCable.AddCheckPoint( vbox1, 1, coord1, vect1);
85 :
86 : // Then, let's cross the boundary ! You just need
87 : // to put the next point in the other volume, vBigBox.
88 : // At the moment of creating the second segment, it will
89 : // be inserted in this volume. That is why the point 1 had to
90 : // be at the boundary, because otherwise the second segment
91 : // between de points 1 and 2 would have been inserted in the
92 : // vBigBox but in the same time would have cross its
93 : // boundary ...
94 : Double_t coord2[3] = {-2,6,4}; // coord. syst. of vBigBox !
95 : Double_t vect2[3]= {1,1,0.5};
96 : roundCable.AddCheckPoint( vBigBox, 2, coord2, vect2);
97 :
98 : Double_t coord3[3] = {4,6,4};
99 : Double_t vect3[3]= {-1,0,0};
100 : roundCable.AddCheckPoint( vBigBox, 3, coord3, vect3);
101 :
102 : Double_t coord4[3] = {4,0,-4};
103 : Double_t vect4[3]= {1,0,0};
104 : roundCable.AddCheckPoint( vBigBox, 4, coord4, vect4);
105 :
106 : Double_t coord5[3] = {4,-6,4};
107 : Double_t vect5[3]= {1,0,0};
108 : roundCable.AddCheckPoint( vBigBox, 5, coord5, vect5);
109 :
110 : Double_t coord6[3] = {7,-6,4};
111 : Double_t vect6[3]= {1,0,0};
112 : roundCable.AddCheckPoint( vBigBox, 6, coord6, vect6);
113 :
114 : Double_t r = 7;
115 : Double_t angle = 70*TMath::DegToRad();
116 : Double_t coord7[3] = {coord6[0] +r*sin(angle), coord6[1],
117 : coord6[2] -r*(1-cos(angle)) };
118 : Double_t vect7[3]= {r*cos(angle),0,-r*sin(angle)};
119 : roundCable.AddCheckPoint( vBigBox, 7, coord7, vect7);
120 :
121 : Double_t coord8[3] = { coord7[0]+vect7[0], coord7[1]+vect7[1],-10};
122 : Double_t vect8[3]= {0,0,1};
123 : roundCable.AddCheckPoint( vBigBox, 8, coord8, vect8);
124 :
125 : // ****** Creating the corresponding volume ******
126 : // Since the container volumes of the check points have
127 : // been recorded, this can be done at any moments, providing
128 : // that the container volumes are found in the sub-nodes
129 : // of the initial node (the top volume of the TGeoManager or
130 : // the volume set in SetInitialNode(TGeoVolume*) function)
131 :
132 : roundCable.SetInitialNode(vBigBox); //Set the root node
133 : roundCable.CreateAndInsertCableSegment( 1);
134 : // This command means : create the segment between point 0
135 : // and point 1. The segment is automatically inserted in the
136 : // container volume of point 1.
137 :
138 : roundCable.CreateAndInsertCableSegment( 2);
139 : roundCable.CreateAndInsertCableSegment( 3);
140 :
141 : // The following segment is going to be a torus segment.
142 : // The radius and position of the torus is defined by the
143 : // orthogonal vector of point 4 (the orientation of this vector
144 : // and the position of the 2 check points are enough to define
145 : // completely the torus)
146 : roundCable.CreateAndInsertTorusSegment( 4, 180);
147 : // The second argument is an additionnal rotation of the
148 : // segment around the axis defined by the 2 check points.
149 :
150 : roundCable.CreateAndInsertTorusSegment( 5);
151 : roundCable.CreateAndInsertCableSegment( 6);
152 : roundCable.CreateAndInsertTorusSegment( 7,180);
153 : roundCable.CreateAndInsertCableSegment( 8);
154 :
155 : */
156 :
157 :
158 :
159 116 : ClassImp(AliITSv11GeomCableRound)
160 :
161 : //________________________________________________________________________
162 : AliITSv11GeomCableRound::
163 : AliITSv11GeomCableRound(const char* name, Double_t radius) :
164 15 : AliITSv11GeomCable(name),
165 15 : fRadius(radius),
166 15 : fNlayer(0),
167 15 : fPhiMin(0),
168 15 : fPhiMax(360)
169 75 : {
170 : // Constructor
171 480 : for (Int_t i=0; i<fgkCableMaxLayer ; i++) {
172 225 : fLayThickness[i] = 0;
173 225 : fLayColor[i] = 0;
174 225 : fLayMedia[i] = 0;
175 : };
176 30 : }
177 : /*
178 : //________________________________________________________________________
179 : AliITSv11GeomCableRound::AliITSv11GeomCableRound(const AliITSv11GeomCableRound &s) :
180 : AliITSv11GeomCable(s),fRadius(s.fRadius),fNlayer(s.fNlayer),fPhiMin(s.fPhiMin),
181 : fPhiMax(s.fPhiMax)
182 : {
183 : // Copy Constructor
184 : for (Int_t i=0; i<s.fNlayer; i++) {
185 : fLayThickness[i] = s.fLayThickness[i];
186 : fLayMedia[i] = s.fLayMedia[i];
187 : fLayColor[i] = s.fLayColor[i];
188 : }
189 : }
190 :
191 : //________________________________________________________________________
192 : AliITSv11GeomCableRound& AliITSv11GeomCableRound::
193 : operator=(const AliITSv11GeomCableRound &s) {
194 : // Assignment operator
195 : // Not fully inplemented yet !!!
196 :
197 : if(&s == this) return *this;
198 : *this = s;
199 : fRadius = s.fRadius;
200 : fPhiMin = s.fPhiMin;
201 : fPhiMax = s.fPhiMax;
202 : fNlayer = s.fNlayer;
203 : for (Int_t i=0; i<s.fNlayer; i++) {
204 : fLayThickness[i] = s.fLayThickness[i];
205 : fLayMedia[i] = s.fLayMedia[i];
206 : fLayColor[i] = s.fLayColor[i];
207 : };
208 : return *this;
209 : }
210 : */
211 : //________________________________________________________________________
212 : Int_t AliITSv11GeomCableRound::GetPoint( Int_t iCheckPt, Double_t *coord)
213 : const {
214 : // Get check point #iCheckPt
215 204 : TVectorD *coordVector =(TVectorD *)fPointArray.UncheckedAt(2*iCheckPt);
216 : #if ROOT_VERSION_CODE < ROOT_VERSION(4,0,0)
217 : CopyFrom(coord, coordVector->GetElements());
218 : #else
219 102 : CopyFrom(coord, coordVector->GetMatrixArray());
220 : #endif
221 102 : return kTRUE;
222 : }
223 :
224 : //________________________________________________________________________
225 : Int_t AliITSv11GeomCableRound::GetVect( Int_t iCheckPt, Double_t *coord)
226 : const {
227 : //
228 : // Get vector transverse to the section at point #iCheckPt
229 : //
230 :
231 204 : TVectorD *coordVector =(TVectorD *)fPointArray.UncheckedAt(2*iCheckPt+1);
232 : #if ROOT_VERSION_CODE < ROOT_VERSION(4,0,0)
233 : CopyFrom(coord, coordVector->GetElements());
234 : #else
235 102 : CopyFrom(coord, coordVector->GetMatrixArray());
236 : #endif
237 102 : return kTRUE;
238 : }
239 :
240 : //________________________________________________________________________
241 : void AliITSv11GeomCableRound::AddCheckPoint( TGeoVolume *vol, Int_t iCheckPt,
242 : Double_t *coord, Double_t *orthVect)
243 : {
244 : //
245 : // Add point #iCheckPt and its transverse vector. Point is added at (i) in
246 : // fPointArray and the vector is added at (i+1)
247 : //
248 :
249 :
250 132 : if (iCheckPt>=fVolumeArray.GetEntriesFast()) {
251 66 : fVolumeArray.AddLast(vol);
252 66 : TVectorD *point = new TVectorD(3,coord);
253 66 : TVectorD *vect = new TVectorD(3,orthVect);
254 66 : fPointArray.AddLast(point);
255 66 : fPointArray.AddLast(vect);
256 :
257 66 : } else if ((iCheckPt >= 0)&&(iCheckPt < fVolumeArray.GetEntriesFast())) {
258 0 : fVolumeArray.AddAt(vol, iCheckPt);
259 0 : TVectorD *point = new TVectorD(3,coord);
260 0 : TVectorD *vect = new TVectorD(3,orthVect);
261 0 : fPointArray.AddAt(point, iCheckPt*2 );
262 0 : fPointArray.AddAt(vect, iCheckPt*2+1);
263 0 : };
264 66 : }
265 :
266 : //________________________________________________________________________
267 : void AliITSv11GeomCableRound::PrintCheckPoints() const {
268 : // Print all check points
269 :
270 0 : printf(" ---\n Printing all check points of the round cable\n");
271 0 : for (Int_t i = 0; i<fVolumeArray.GetEntriesFast(); i++) {
272 0 : TVectorD *coordVector = (TVectorD *)fPointArray.UncheckedAt(i*2);
273 : //TVectorD *vectVector = (TVectorD *)fPointArray.UncheckedAt(i*2+1);
274 0 : Double_t coord[3];
275 : #if ROOT_VERSION_CODE < ROOT_VERSION(4,0,0)
276 : CopyFrom(coord, coordVector->GetElements());
277 : #else
278 0 : CopyFrom(coord, coordVector->GetMatrixArray());
279 : #endif
280 0 : printf(" ( %.2f, %.2f, %.2f )\n", coord[0], coord[1], coord[2]);
281 0 : };
282 0 : }
283 :
284 :
285 : //________________________________________________________________________
286 : TGeoVolume* AliITSv11GeomCableRound::CreateAndInsertCableSegment(Int_t p2,
287 : TGeoCombiTrans** ct)
288 : {
289 : // Creates a cable segment between points p1 and p2.
290 : //
291 : // The segment volume is created inside the volume containing point2
292 : // Therefore this segment should be defined in this volume only.
293 : // I mean here that, if the previous point is in another volume,
294 : // it should be just at the border between the 2 volumes. Also the
295 : // orientation vector of the previous point should be othogonal to
296 : // the surface between the 2 volumes.
297 :
298 : TGeoNode *mainNode;
299 2 : if (fInitialNode==0) {
300 0 : TObjArray *nodes = gGeoManager->GetListOfNodes();
301 0 : if (nodes->GetEntriesFast()==0) return 0;
302 0 : mainNode = (TGeoNode *) nodes->UncheckedAt(0);
303 0 : } else {
304 : mainNode = fInitialNode;
305 : };
306 :
307 1 : Int_t p1 = p2 - 1;
308 1 : TGeoVolume *p1Vol = GetVolume(p1);
309 1 : TGeoVolume *p2Vol = GetVolume(p2);
310 :
311 1 : ResetCheckDaughter();
312 1 : fCurrentVol = p1Vol;
313 1 : if (! CheckDaughter(mainNode)) {
314 0 : printf("Error::volume containing point is not visible in node tree!\n");
315 0 : return 0;
316 : };
317 :
318 1 : Double_t coord1[3], coord2[3], vect1[3], vect2[3];
319 : //=================================================
320 : // Get p1 position in the systeme of p2
321 1 : if (p1Vol!=p2Vol) {
322 :
323 0 : Int_t p1nodeInd[fgkCableMaxNodeLevel];
324 0 : for (Int_t i=0; i<fgkCableMaxNodeLevel; i++) p1nodeInd[i]=fNodeInd[i];
325 : Int_t p1volLevel = 0;
326 0 : while (p1nodeInd[p1volLevel]!=-1) p1volLevel++;
327 0 : p1volLevel--;
328 :
329 0 : ResetCheckDaughter();
330 0 : fCurrentVol = p2Vol;
331 0 : if (! CheckDaughter(mainNode)) {
332 0 : printf("Error::volume containing point is not visible in node tree!\n");
333 0 : return 0;
334 : };
335 0 : Int_t p2nodeInd[fgkCableMaxNodeLevel];
336 0 : for (Int_t i=0; i<fgkCableMaxNodeLevel; i++) p2nodeInd[i]=fNodeInd[i];
337 : Int_t commonMotherLevel = 0;
338 0 : while (p1nodeInd[commonMotherLevel]==fNodeInd[commonMotherLevel])
339 0 : commonMotherLevel++;
340 0 : commonMotherLevel--;
341 : Int_t p2volLevel = 0;
342 0 : while (fNodeInd[p2volLevel]!=-1) p2volLevel++;
343 0 : p2volLevel--;
344 :
345 : // Get coord and vect of p1 in the common mother reference system
346 0 : GetCheckPoint(p1, 0, p1volLevel-commonMotherLevel, coord1);
347 0 : GetCheckVect( p1, 0, p1volLevel-commonMotherLevel, vect1);
348 : // Translate them in the reference system of the volume containing p2
349 0 : TGeoNode *pathNode[fgkCableMaxNodeLevel];
350 0 : pathNode[0] = mainNode;
351 0 : for (Int_t i=0; i<=p2volLevel; i++) {
352 0 : pathNode[i+1] = pathNode[i]->GetDaughter(p2nodeInd[i]);
353 : };
354 0 : Double_t globalCoord1[3] = {coord1[0], coord1[1], coord1[2]};
355 0 : Double_t globalVect1[3] = {vect1[0], vect1[1], vect1[2]};
356 :
357 0 : for (Int_t i = commonMotherLevel+1; i<=p2volLevel; i++) {
358 0 : pathNode[i+1]->GetMatrix()->MasterToLocal(globalCoord1, coord1);
359 0 : pathNode[i+1]->GetMatrix()->MasterToLocalVect(globalVect1, vect1);
360 0 : CopyFrom(globalCoord1, coord1);
361 0 : CopyFrom(globalVect1, vect1);
362 : };
363 0 : } else {
364 1 : GetCheckPoint(p1, 0, 0, coord1);
365 1 : GetCheckVect(p1, 0, 0, vect1);
366 : };
367 :
368 : //=================================================
369 : // Get p2 position in the systeme of p2
370 1 : GetCheckPoint(p2, 0, 0, coord2);
371 1 : GetCheckVect(p2, 0, 0, vect2);
372 :
373 1 : Double_t cx = (coord1[0]+coord2[0])/2;
374 1 : Double_t cy = (coord1[1]+coord2[1])/2;
375 1 : Double_t cz = (coord1[2]+coord2[2])/2;
376 1 : Double_t dx = coord2[0]-coord1[0];
377 1 : Double_t dy = coord2[1]-coord1[1];
378 1 : Double_t dz = coord2[2]-coord1[2];
379 :
380 : //=================================================
381 : // Positionning of the segment between the 2 points
382 1 : if ((dy<1e-31)&&(dy>0)) dy = 1e-31;
383 1 : if ((dz<1e-31)&&(dz>0)) dz = 1e-31;
384 1 : if ((dy>-1e-31)&&(dy<0)) dy = -1e-31;
385 1 : if ((dz>-1e-31)&&(dz<0)) dz = -1e-31;
386 :
387 1 : Double_t angleRot1 = -TMath::ATan2(dx,dy);
388 1 : Double_t planDiagL = TMath::Sqrt(dy*dy+dx*dx);
389 1 : Double_t angleRotDiag = -TMath::ATan2(planDiagL,dz);
390 2 : TGeoRotation *rot = new TGeoRotation("",angleRot1*TMath::RadToDeg(),
391 1 : angleRotDiag*TMath::RadToDeg(),
392 : 0);
393 1 : Double_t localVect1[3], localVect2[3];
394 1 : rot->MasterToLocalVect(vect1, localVect1);
395 1 : rot->MasterToLocalVect(vect2, localVect2);
396 1 : TGeoTranslation *trans = new TGeoTranslation("",cx, cy, cz);
397 :
398 : //=================================================
399 : // Create the segment and add it to the mother volume
400 1 : TGeoVolume *vCableSeg = CreateSegment(coord1, coord2,
401 : localVect1, localVect2, p2);
402 :
403 1 : TGeoCombiTrans *combi = new TGeoCombiTrans(*trans, *rot);
404 1 : p2Vol->AddNode(vCableSeg, p2, combi);
405 : //=================================================
406 2 : delete rot;
407 2 : delete trans;
408 :
409 1 : if (fDebug) {
410 0 : printf("---\n Cable segment points : ");
411 0 : printf("%f, %f, %f\n",coord1[0], coord1[1], coord1[2]);
412 0 : printf("%f, %f, %f\n",coord2[0], coord2[1], coord2[2]);
413 0 : };
414 : // #include <TGeoSphere.h>
415 : // TGeoMedium *airSDD = gGeoManager->GetMedium("ITS_AIR$");
416 : // TGeoSphere *sphere = new TGeoSphere(0, 0.15);
417 : // TGeoVolume *vSphere = new TGeoVolume("", sphere, airSDD);
418 : // TGeoTranslation *trC = new TGeoTranslation("", cx, cy, cz);
419 : // TGeoTranslation *tr1 = new TGeoTranslation("",coord1[0],
420 : // coord1[1],coord1[2]);
421 : // TGeoTranslation *tr2 = new TGeoTranslation("",coord2[0],
422 : // coord2[1],coord2[2]);
423 : // p2Vol->AddNode(vSphere, p2*3-2, trC);
424 : // p2Vol->AddNode(vSphere, p2*3-1, tr1);
425 : // p2Vol->AddNode(vSphere, p2*3 , tr2);
426 :
427 2 : if (ct) *ct = combi;
428 : return vCableSeg;
429 3 : }
430 :
431 : //________________________________________________________________________
432 : TGeoVolume* AliITSv11GeomCableRound::CreateAndInsertTubeSegment(Int_t p2,
433 : TGeoCombiTrans** ct)
434 : {
435 : // Creates a cable segment between points p1 and p2.
436 : //
437 : // This creates simple tube sections, i.e. the cable ends are
438 : // cutted perpendicularly to the tube axis. The method has to
439 : // be used only in this simple case, in ordder to save some memory
440 :
441 : TGeoNode *mainNode;
442 60 : if (fInitialNode==0) {
443 0 : TObjArray *nodes = gGeoManager->GetListOfNodes();
444 0 : if (nodes->GetEntriesFast()==0) return 0;
445 0 : mainNode = (TGeoNode *) nodes->UncheckedAt(0);
446 0 : } else {
447 : mainNode = fInitialNode;
448 : };
449 :
450 30 : Int_t p1 = p2 - 1;
451 30 : TGeoVolume *p1Vol = GetVolume(p1);
452 30 : TGeoVolume *p2Vol = GetVolume(p2);
453 :
454 30 : ResetCheckDaughter();
455 30 : fCurrentVol = p1Vol;
456 30 : if (! CheckDaughter(mainNode)) {
457 0 : printf("Error::volume containing point is not visible in node tree!\n");
458 0 : return 0;
459 : };
460 :
461 30 : Double_t coord1[3], coord2[3], vect1[3], vect2[3];
462 : //=================================================
463 : // Get p1 position in the systeme of p2
464 30 : if (p1Vol!=p2Vol) {
465 :
466 0 : Int_t p1nodeInd[fgkCableMaxNodeLevel];
467 0 : for (Int_t i=0; i<fgkCableMaxNodeLevel; i++) p1nodeInd[i]=fNodeInd[i];
468 : Int_t p1volLevel = 0;
469 0 : while (p1nodeInd[p1volLevel]!=-1) p1volLevel++;
470 0 : p1volLevel--;
471 :
472 0 : ResetCheckDaughter();
473 0 : fCurrentVol = p2Vol;
474 0 : if (! CheckDaughter(mainNode)) {
475 0 : printf("Error::volume containing point is not visible in node tree!\n");
476 0 : return 0;
477 : };
478 0 : Int_t p2nodeInd[fgkCableMaxNodeLevel];
479 0 : for (Int_t i=0; i<fgkCableMaxNodeLevel; i++) p2nodeInd[i]=fNodeInd[i];
480 : Int_t commonMotherLevel = 0;
481 0 : while (p1nodeInd[commonMotherLevel]==fNodeInd[commonMotherLevel])
482 0 : commonMotherLevel++;
483 0 : commonMotherLevel--;
484 : Int_t p2volLevel = 0;
485 0 : while (fNodeInd[p2volLevel]!=-1) p2volLevel++;
486 0 : p2volLevel--;
487 :
488 : // Get coord and vect of p1 in the common mother reference system
489 0 : GetCheckPoint(p1, 0, p1volLevel-commonMotherLevel, coord1);
490 0 : GetCheckVect( p1, 0, p1volLevel-commonMotherLevel, vect1);
491 : // Translate them in the reference system of the volume containing p2
492 0 : TGeoNode *pathNode[fgkCableMaxNodeLevel];
493 0 : pathNode[0] = mainNode;
494 0 : for (Int_t i=0; i<=p2volLevel; i++) {
495 0 : pathNode[i+1] = pathNode[i]->GetDaughter(p2nodeInd[i]);
496 : };
497 0 : Double_t globalCoord1[3] = {coord1[0], coord1[1], coord1[2]};
498 0 : Double_t globalVect1[3] = {vect1[0], vect1[1], vect1[2]};
499 :
500 0 : for (Int_t i = commonMotherLevel+1; i<=p2volLevel; i++) {
501 0 : pathNode[i+1]->GetMatrix()->MasterToLocal(globalCoord1, coord1);
502 0 : pathNode[i+1]->GetMatrix()->MasterToLocalVect(globalVect1, vect1);
503 0 : CopyFrom(globalCoord1, coord1);
504 0 : CopyFrom(globalVect1, vect1);
505 : };
506 0 : } else {
507 30 : GetCheckPoint(p1, 0, 0, coord1);
508 30 : GetCheckVect(p1, 0, 0, vect1);
509 : };
510 :
511 : //=================================================
512 : // Get p2 position in the systeme of p2
513 30 : GetCheckPoint(p2, 0, 0, coord2);
514 30 : GetCheckVect(p2, 0, 0, vect2);
515 :
516 30 : Double_t cx = (coord1[0]+coord2[0])/2;
517 30 : Double_t cy = (coord1[1]+coord2[1])/2;
518 30 : Double_t cz = (coord1[2]+coord2[2])/2;
519 30 : Double_t dx = coord2[0]-coord1[0];
520 30 : Double_t dy = coord2[1]-coord1[1];
521 30 : Double_t dz = coord2[2]-coord1[2];
522 :
523 : //=================================================
524 : // Positionning of the segment between the 2 points
525 30 : if ((dy<1e-31)&&(dy>0)) dy = 1e-31;
526 30 : if ((dz<1e-31)&&(dz>0)) dz = 1e-31;
527 30 : if ((dy>-1e-31)&&(dy<0)) dy = -1e-31;
528 30 : if ((dz>-1e-31)&&(dz<0)) dz = -1e-31;
529 :
530 30 : Double_t angleRot1 = -TMath::ATan2(dx,dy);
531 30 : Double_t planDiagL = TMath::Sqrt(dy*dy+dx*dx);
532 30 : Double_t angleRotDiag = -TMath::ATan2(planDiagL,dz);
533 60 : TGeoRotation *rot = new TGeoRotation("",angleRot1*TMath::RadToDeg(),
534 30 : angleRotDiag*TMath::RadToDeg(),
535 : 0);
536 30 : TGeoTranslation *trans = new TGeoTranslation("",cx, cy, cz);
537 :
538 : //=================================================
539 : // Create the segment and add it to the mother volume
540 30 : TGeoVolume *vCableSeg = CreateTubeSegment( coord1,coord2, p2);
541 :
542 30 : TGeoCombiTrans *combi = new TGeoCombiTrans(*trans, *rot);
543 30 : p2Vol->AddNode(vCableSeg, p2, combi);
544 : //=================================================
545 60 : delete rot;
546 60 : delete trans;
547 :
548 30 : if (fDebug) {
549 0 : printf("---\n Cable segment points : ");
550 0 : printf("%f, %f, %f\n",coord1[0], coord1[1], coord1[2]);
551 0 : printf("%f, %f, %f\n",coord2[0], coord2[1], coord2[2]);
552 0 : };
553 :
554 30 : if (ct) *ct = combi;
555 : return vCableSeg;
556 60 : }
557 :
558 : //________________________________________________________________________
559 : TGeoVolume* AliITSv11GeomCableRound::CreateAndInsertTorusSegment(Int_t p2,
560 : Double_t rotation,
561 : TGeoCombiTrans** ct)
562 : {
563 : // Create a torus cable segment between points p1 and p2.
564 : // The radius and position of the torus is defined by the
565 : // perpendicular vector of point p2 (the orientation of this vector
566 : // and the position of the 2 check points are enough to completely
567 : // define the torus)
568 :
569 : TGeoNode *mainNode;
570 40 : if (fInitialNode==0) {
571 0 : TObjArray *nodes = gGeoManager->GetListOfNodes();
572 0 : if (nodes->GetEntriesFast()==0) return 0;
573 0 : mainNode = (TGeoNode *) nodes->UncheckedAt(0);
574 0 : } else {
575 : mainNode = fInitialNode;
576 : };
577 :
578 20 : Int_t p1 = p2 - 1;
579 20 : TGeoVolume *p1Vol = GetVolume(p1);
580 20 : TGeoVolume *p2Vol = GetVolume(p2);
581 :
582 20 : ResetCheckDaughter();
583 20 : fCurrentVol = p1Vol;
584 20 : if (! CheckDaughter(mainNode)) {
585 0 : printf("Error::volume containing point is not visible in node tree!\n");
586 0 : return 0;
587 : };
588 :
589 20 : Double_t coord1[3], coord2[3], vect1[3], vect2[3];
590 : //=================================================
591 : // Get p1 position in the systeme of p2
592 20 : if (p1Vol!=p2Vol) {
593 :
594 0 : Int_t p1nodeInd[fgkCableMaxNodeLevel];
595 0 : for (Int_t i=0; i<fgkCableMaxNodeLevel; i++) p1nodeInd[i]=fNodeInd[i];
596 : Int_t p1volLevel = 0;
597 0 : while (p1nodeInd[p1volLevel]!=-1) p1volLevel++;
598 0 : p1volLevel--;
599 :
600 0 : ResetCheckDaughter();
601 0 : fCurrentVol = p2Vol;
602 0 : if (! CheckDaughter(mainNode)) {
603 0 : printf("Error::volume containing point is not visible in node tree!\n");
604 0 : return 0;
605 : };
606 0 : Int_t p2nodeInd[fgkCableMaxNodeLevel];
607 0 : for (Int_t i=0; i<fgkCableMaxNodeLevel; i++) p2nodeInd[i]=fNodeInd[i];
608 : Int_t commonMotherLevel = 0;
609 0 : while (p1nodeInd[commonMotherLevel]==fNodeInd[commonMotherLevel])
610 0 : commonMotherLevel++;
611 0 : commonMotherLevel--;
612 : Int_t p2volLevel = 0;
613 0 : while (fNodeInd[p2volLevel]!=-1) p2volLevel++;
614 0 : p2volLevel--;
615 :
616 : // Get coord and vect of p1 in the common mother reference system
617 0 : GetCheckPoint(p1, 0, p1volLevel-commonMotherLevel, coord1);
618 0 : GetCheckVect( p1, 0, p1volLevel-commonMotherLevel, vect1);
619 : // Translate them in the reference system of the volume containing p2
620 0 : TGeoNode *pathNode[fgkCableMaxNodeLevel];
621 0 : pathNode[0] = mainNode;
622 0 : for (Int_t i=0; i<=p2volLevel; i++) {
623 0 : pathNode[i+1] = pathNode[i]->GetDaughter(p2nodeInd[i]);
624 : };
625 0 : Double_t globalCoord1[3] = {coord1[0], coord1[1], coord1[2]};
626 0 : Double_t globalVect1[3] = {vect1[0], vect1[1], vect1[2]};
627 :
628 0 : for (Int_t i = commonMotherLevel+1; i<=p2volLevel; i++) {
629 0 : pathNode[i+1]->GetMatrix()->MasterToLocal(globalCoord1, coord1);
630 0 : pathNode[i+1]->GetMatrix()->MasterToLocalVect(globalVect1, vect1);
631 0 : CopyFrom(globalCoord1, coord1);
632 0 : CopyFrom(globalVect1, vect1);
633 : };
634 0 : } else {
635 20 : GetCheckPoint(p1, 0, 0, coord1);
636 20 : GetCheckVect(p1, 0, 0, vect1);
637 : };
638 :
639 : //=================================================
640 : // Get p2 position in the systeme of p2
641 20 : GetCheckPoint(p2, 0, 0, coord2);
642 20 : GetCheckVect(p2, 0, 0, vect2);
643 :
644 20 : Double_t cx = (coord1[0]+coord2[0])/2;
645 20 : Double_t cy = (coord1[1]+coord2[1])/2;
646 20 : Double_t cz = (coord1[2]+coord2[2])/2;
647 20 : Double_t dx = coord2[0]-coord1[0];
648 20 : Double_t dy = coord2[1]-coord1[1];
649 20 : Double_t dz = coord2[2]-coord1[2];
650 20 : Double_t length = TMath::Sqrt(dx*dx+dy*dy+dz*dz);
651 :
652 : //=================================================
653 : // Positionning of the segment between the 2 points
654 20 : if ((dy<1e-31)&&(dy>0)) dy = 1e-31;
655 20 : if ((dz<1e-31)&&(dz>0)) dz = 1e-31;
656 20 : if ((dy>-1e-31)&&(dy<0)) dy = -1e-31;
657 20 : if ((dz>-1e-31)&&(dz<0)) dz = -1e-31;
658 :
659 20 : Double_t angleRot1 = -TMath::ATan2(dx,dy);
660 20 : Double_t planDiagL = TMath::Sqrt(dy*dy+dx*dx);
661 20 : Double_t angleRotDiag = -TMath::ATan2(planDiagL,dz);
662 :
663 40 : TGeoRotation rotTorusTemp("",angleRot1*TMath::RadToDeg(),
664 20 : angleRotDiag*TMath::RadToDeg(),0);
665 20 : TGeoRotation rotTorusToZ("",0,90,0);
666 20 : rotTorusTemp.MultiplyBy(&rotTorusToZ, kTRUE);
667 20 : Double_t localVect2[3];
668 20 : rotTorusTemp.MasterToLocalVect(vect2, localVect2);
669 20 : if (localVect2[1]<0) {
670 4 : localVect2[0] = -localVect2[0];
671 4 : localVect2[1] = -localVect2[1];
672 4 : localVect2[2] = -localVect2[2];
673 4 : };
674 60 : Double_t normVect2 = TMath::Sqrt(localVect2[0]*localVect2[0]+
675 40 : localVect2[1]*localVect2[1]+
676 20 : localVect2[2]*localVect2[2]);
677 : Double_t axisX[3] = {1,0,0};
678 40 : Double_t cosangleTorusSeg = (localVect2[0]*axisX[0]+
679 40 : localVect2[1]*axisX[1]+
680 40 : localVect2[2]*axisX[2])/normVect2;
681 20 : Double_t angleTorusSeg = TMath::ACos(cosangleTorusSeg)*TMath::RadToDeg();
682 :
683 40 : TGeoRotation rotTorus("",angleRot1*TMath::RadToDeg(),
684 20 : angleRotDiag*TMath::RadToDeg(),
685 20 : 180-angleTorusSeg+rotation);
686 20 : rotTorus.MultiplyBy(&rotTorusToZ, kTRUE);
687 20 : rotTorus.MasterToLocalVect(vect2, localVect2);
688 20 : if (localVect2[1]<0) {
689 4 : localVect2[0] = -localVect2[0];
690 4 : localVect2[1] = -localVect2[1];
691 4 : localVect2[2] = -localVect2[2];
692 4 : };
693 60 : normVect2 = TMath::Sqrt(localVect2[0]*localVect2[0]+
694 40 : localVect2[1]*localVect2[1]+
695 20 : localVect2[2]*localVect2[2]);
696 : Double_t axisY[3] = {0,1,0};
697 40 : Double_t cosPhi = (localVect2[0]*axisY[0]+localVect2[1]*axisY[1]+
698 40 : localVect2[2]*axisY[2])/normVect2;
699 20 : Double_t torusPhi1 = TMath::ACos(cosPhi);
700 20 : Double_t torusR = (length/2)/TMath::Sin(torusPhi1);
701 20 : torusPhi1 = torusPhi1*TMath::RadToDeg();
702 20 : Double_t perpLength = TMath::Sqrt(torusR*torusR-length*length/4);
703 20 : Double_t localTransT[3] = {-perpLength,0,0};
704 20 : Double_t globalTransT[3];
705 20 : rotTorus.LocalToMasterVect(localTransT, globalTransT);
706 40 : TGeoTranslation transTorus("",cx+globalTransT[0],cy+globalTransT[1],
707 20 : cz+globalTransT[2]);
708 :
709 40 : TGeoCombiTrans *combiTorus = new TGeoCombiTrans(transTorus, rotTorus);
710 :
711 : //=================================================
712 : // Create the segment and add it to the mother volume
713 20 : TGeoVolume *vCableSegT = CreateTorus(torusPhi1, torusR, p2);
714 20 : p2Vol->AddNode(vCableSegT, p2, combiTorus);
715 :
716 20 : if (fDebug) {
717 0 : printf("---\n Cable segment points : ");
718 0 : printf("%f, %f, %f\n",coord1[0], coord1[1], coord1[2]);
719 0 : printf("%f, %f, %f\n",coord2[0], coord2[1], coord2[2]);
720 : };
721 :
722 20 : if (ct) *ct = combiTorus;
723 : return vCableSegT;
724 60 : }
725 :
726 : //________________________________________________________________________
727 : TGeoVolume *AliITSv11GeomCableRound::CreateSegment( const Double_t *coord1,
728 : const Double_t *coord2,
729 : Double_t *localVect1,
730 : Double_t *localVect2, Int_t p)
731 : {
732 : // Create a cylindrical segment and its layers. The tube section is cutted by
733 : // two planes, defined by the normal vectors localVect1 and localVect2
734 :
735 : //=================================================
736 : // Calculate segment "deformation"
737 2 : Double_t dx = coord2[0]-coord1[0];
738 1 : Double_t dy = coord2[1]-coord1[1];
739 1 : Double_t dz = coord2[2]-coord1[2];
740 1 : Double_t length = TMath::Sqrt(dx*dx+dy*dy+dz*dz);
741 :
742 : // normal vectors have to point outside the TGeoCtub :
743 1 : if (-localVect1[2]<0) {
744 1 : localVect1[0] = -localVect1[0];
745 1 : localVect1[1] = -localVect1[1];
746 1 : localVect1[2] = -localVect1[2];
747 1 : };
748 1 : if (localVect2[2]<0) {
749 0 : localVect2[0] = -localVect2[0];
750 0 : localVect2[1] = -localVect2[1];
751 0 : localVect2[2] = -localVect2[2];
752 0 : };
753 : //=================================================
754 : // Create the segment
755 2 : TGeoCtub *cableSeg = new TGeoCtub(0, fRadius, length/2, fPhiMin, fPhiMax,
756 1 : localVect1[0],localVect1[1],localVect1[2],
757 1 : localVect2[0],localVect2[1],localVect2[2]);
758 :
759 1 : TGeoMedium *skinMedia = fLayMedia[fNlayer-1];
760 1 : char name[100];
761 1 : snprintf(name, 100, "%s_%i",GetName(), p);
762 1 : TGeoVolume *vCableSeg = new TGeoVolume(name, cableSeg, skinMedia);
763 1 : vCableSeg->SetLineColor(fLayColor[fNlayer-1]);
764 :
765 : // add all cable layers
766 1 : Double_t layThickness[100+1]; // 100 layers max !!!
767 1 : layThickness[0] = 0;
768 4 : for (Int_t iLay=0; iLay<fNlayer-1; iLay++) {
769 :
770 1 : layThickness[iLay+1] = fLayThickness[iLay]+layThickness[iLay];
771 2 : TGeoCtub *lay = new TGeoCtub(layThickness[iLay], layThickness[iLay+1],
772 1 : length/2, fPhiMin, fPhiMax,
773 1 : localVect1[0],localVect1[1],localVect1[2],
774 1 : localVect2[0],localVect2[1],localVect2[2]);
775 :
776 1 : TGeoVolume *vLay = new TGeoVolume("vCableSegLay", lay, fLayMedia[iLay]);
777 1 : vLay->SetLineColor(fLayColor[iLay]);
778 1 : vCableSeg->AddNode(vLay, iLay+1, 0);
779 : };
780 :
781 : //vCableSeg->SetVisibility(kFALSE);
782 1 : return vCableSeg;
783 1 : }
784 :
785 :
786 : //________________________________________________________________________
787 : TGeoVolume *AliITSv11GeomCableRound::CreateTubeSegment( const Double_t *coord1,
788 : const Double_t *coord2,
789 : Int_t p)
790 : {
791 : // Create a cylindrical segment and its layers
792 :
793 : //=================================================
794 : // Calculate segment "deformation"
795 60 : Double_t dx = coord2[0]-coord1[0];
796 30 : Double_t dy = coord2[1]-coord1[1];
797 30 : Double_t dz = coord2[2]-coord1[2];
798 30 : Double_t length = TMath::Sqrt(dx*dx+dy*dy+dz*dz);
799 :
800 : //=================================================
801 : // Create the segment
802 :
803 30 : TGeoTubeSeg *cableSeg = new TGeoTubeSeg(0, fRadius, length/2, fPhiMin, fPhiMax);
804 :
805 30 : TGeoMedium *skinMedia = fLayMedia[fNlayer-1];
806 30 : char name[100];
807 30 : snprintf(name, 100, "%s_%i",GetName(), p);
808 30 : TGeoVolume *vCableSeg = new TGeoVolume(name, cableSeg, skinMedia);
809 30 : vCableSeg->SetLineColor(fLayColor[fNlayer-1]);
810 :
811 : // add all cable layers
812 30 : Double_t layThickness[100+1]; // 100 layers max !!!
813 30 : layThickness[0] = 0;
814 120 : for (Int_t iLay=0; iLay<fNlayer-1; iLay++) {
815 :
816 30 : layThickness[iLay+1] = fLayThickness[iLay]+layThickness[iLay];
817 60 : TGeoTubeSeg*lay = new TGeoTubeSeg(layThickness[iLay], layThickness[iLay+1],
818 30 : length/2, fPhiMin, fPhiMax);
819 30 : TGeoVolume *vLay = new TGeoVolume("vCableSegLay", lay, fLayMedia[iLay]);
820 30 : vLay->SetLineColor(fLayColor[iLay]);
821 30 : vCableSeg->AddNode(vLay, iLay+1, 0);
822 : };
823 :
824 : //vCableSeg->SetVisibility(kFALSE);
825 30 : return vCableSeg;
826 30 : }
827 :
828 :
829 : //________________________________________________________________________
830 : TGeoVolume *AliITSv11GeomCableRound::CreateTorus( const Double_t &phi,
831 : const Double_t &r, Int_t p)
832 : {
833 : // Create one torus segment and its layers
834 :
835 40 : Double_t torusR = r;
836 : // Double_t torusPhi1 = phi;
837 : // Double_t torusDPhi = -2*torusPhi1; // bug in root ...
838 20 : Double_t torusPhi1 = 360-phi;
839 20 : Double_t torusDPhi = 2*phi;
840 :
841 : // // Create the segment, it will also work as the last layer
842 20 : TGeoTorus *cableSeg = new TGeoTorus(torusR, 0, fRadius, torusPhi1, torusDPhi);
843 20 : TGeoMedium *skinMedia = fLayMedia[fNlayer-1];
844 20 : char name[100];
845 20 : snprintf(name, 100, "%s_%i",GetName(),p);
846 20 : TGeoVolume *vCableSeg = new TGeoVolume(name, cableSeg, skinMedia);
847 20 : vCableSeg->SetLineColor(fLayColor[fNlayer-1]);
848 :
849 : // add all cable layers but last
850 20 : Double_t layThickness[100+1]; // 100 layers max !!!
851 20 : layThickness[0] = 0;
852 80 : for (Int_t iLay=0; iLay<fNlayer-1; iLay++) {
853 :
854 20 : layThickness[iLay+1] = fLayThickness[iLay]+layThickness[iLay];
855 40 : TGeoTorus *lay = new TGeoTorus(torusR, layThickness[iLay],
856 20 : layThickness[iLay+1],
857 : torusPhi1,torusDPhi);
858 :
859 20 : TGeoVolume *vLay = new TGeoVolume("vCableSegLay",lay,fLayMedia[iLay]);
860 20 : vLay->SetLineColor(fLayColor[iLay]);
861 :
862 20 : vCableSeg->AddNode(vLay, iLay+1,0);
863 : };
864 :
865 : //vCableSeg->SetVisibility(kFALSE);
866 20 : return vCableSeg;
867 20 : }
868 :
869 : //________________________________________________________________________
870 : void AliITSv11GeomCableRound::SetNLayers(Int_t nLayers) {
871 : // Set the total number of layers
872 30 : if((nLayers>0) &&(nLayers<=fgkCableMaxLayer)) {
873 15 : fNlayer = nLayers;
874 90 : for (Int_t i = 0; i<fNlayer; i++) {
875 30 : fLayThickness[i] = 0;
876 30 : fLayMedia[i] = 0;
877 : };
878 15 : };
879 15 : }
880 :
881 : //________________________________________________________________________
882 : Int_t AliITSv11GeomCableRound::SetLayer(Int_t nLayer, Double_t thick,
883 : TGeoMedium *medium, Int_t color) {
884 : // Set layer #nLayer
885 90 : if ((nLayer<0)||(nLayer>=fNlayer)) {
886 0 : printf("Set wrong layer number of the cable\n");
887 0 : return kFALSE;
888 : };
889 30 : if (nLayer>0)
890 15 : if (fLayThickness[nLayer-1]<=0) {
891 0 : printf("You must define cable layer %i first !",nLayer-1);
892 0 : return kFALSE;
893 : };
894 :
895 : Double_t thickTot = 0;
896 90 : for (Int_t i=0; i<nLayer; i++) thickTot += fLayThickness[i];
897 30 : thickTot += thick;
898 30 : if (thickTot-1e-10>fRadius) {
899 0 : printf("Can't add this layer, cable thickness would be higher than total\n");
900 0 : return kFALSE;
901 : };
902 :
903 30 : fLayThickness[nLayer] = thick;
904 30 : fLayMedia[nLayer] = medium;
905 30 : fLayColor[nLayer] = color;
906 :
907 30 : return kTRUE;
908 30 : }
|