]> git.uio.no Git - u/mrichter/AliRoot.git/blob - FMD/AliFMDGeometryBuilder.cxx
Fix tension box position, and wire overlap
[u/mrichter/AliRoot.git] / FMD / AliFMDGeometryBuilder.cxx
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 /* $Id$ */
16 /** @file    AliFMDGeometryBuilder.cxx
17     @author  Christian Holm Christensen <cholm@nbi.dk>
18     @date    Mon Mar 27 12:41:17 2006
19     @brief   Class to build the FMD geometry 
20 */
21 //____________________________________________________________________
22 //                                                                          
23 // Builder of FMD geometry. 
24 //
25 // This class takes care of actually building the geometry using the 
26 // TGeo classes.  Various parameters are fecthed from the
27 // AliFMDGeometry manager.  
28 // Forward Multiplicity Detector based on Silicon wafers. This class
29 // contains the base procedures for the Forward Multiplicity detector
30 // Detector consists of 3 sub-detectors FMD1, FMD2, and FMD3, each of
31 // which has 1 or 2 rings of silicon sensors. 
32 //                                                       
33 // 
34
35 #include <TArrayD.h>            // ROOT_TArrayD
36 #include <TGeoManager.h>        // ROOT_TGeoManager
37 #include <TGeoMatrix.h>         // ROOT_TGeoMatrix
38 #include <TGeoTube.h>           // ROOT_TGeoTube
39 #include <TGeoTrd1.h>           // ROOT_TGeoTrd1
40 #include <TGeoCone.h>           // ROOT_TGeoTrd1
41 #include <TGeoVolume.h>         // ROOT_TGeoVolume
42 #include <TGeoXtru.h>           // ROOT_TGeoXtru
43 #include <TGeoPcon.h>           // ROOT_TGeoPcon
44 #include <TGeoCompositeShape.h>
45 #include <TMath.h>
46 #include <TVector2.h>           // ROOT_TVector2
47 #include <TVector3.h>           // ROOT_TVector3
48 //#include <TGeoMaterial.h>     // ROOT_TGeoMaterial
49 //#include <TGeoMedium.h>               // ROOT_TGeoMedium
50 //#include <TGeoPcon.h>         // ROOT_TGeoPcon
51 //#include <TGeoPolygon.h>      // ROOT_TGeoPolygon
52
53 #include "AliFMDGeometryBuilder.h"      // ALIFMDGEOSIMULATOR_H
54 #include "AliFMDGeometry.h"     // ALIFMDGEOMETRY_H
55 #include "AliFMDDetector.h"     // ALIFMDDETECTOR_H
56 #include "AliFMDRing.h"         // ALIFMDRING_H
57 #include "AliFMD1.h"            // ALIFMD1_H
58 #include "AliFMD2.h"            // ALIFMD2_H
59 #include "AliFMD3.h"            // ALIFMD3_H
60 // #include "AliFMD.h"          // ALIFMD_H
61 #include "AliFMDDebug.h"                // ALILOG_H
62 #include <iostream>
63
64 //====================================================================
65 ClassImp(AliFMDGeometryBuilder)
66 #if 0
67   ; // This is here to keep Emacs for indenting the next line
68 #endif
69
70 //____________________________________________________________________
71 const Char_t* AliFMDGeometryBuilder::fgkActiveName      = "F%cAC";
72 const Char_t* AliFMDGeometryBuilder::fgkSectorName      = "F%cSC";
73 const Char_t* AliFMDGeometryBuilder::fgkStripName       = "F%cST";
74 const Char_t* AliFMDGeometryBuilder::fgkSensorName      = "F%cSE";
75 const Char_t* AliFMDGeometryBuilder::fgkPCBName         = "F%cPB";
76 const Char_t* AliFMDGeometryBuilder::fgkCuName          = "F%cCU";
77 const Char_t* AliFMDGeometryBuilder::fgkChipName        = "F%cCH";
78 const Char_t* AliFMDGeometryBuilder::fgkLongLegName     = "F%cLL";
79 const Char_t* AliFMDGeometryBuilder::fgkShortLegName    = "F%cSL";
80 const Char_t* AliFMDGeometryBuilder::fgkFrontVName      = "F%cFH";
81 const Char_t* AliFMDGeometryBuilder::fgkBackVName       = "F%cBH";
82 const Char_t* AliFMDGeometryBuilder::fgkRingTopName     = "F%cTV";
83 const Char_t* AliFMDGeometryBuilder::fgkRingBotName     = "F%cBV";
84 const Char_t* AliFMDGeometryBuilder::fgkHCName          = "F%dH%c";
85 const Char_t* AliFMDGeometryBuilder::fgkIHCName         = "F%dI%c";
86 const Char_t* AliFMDGeometryBuilder::fgkNoseName        = "F3SN";
87 const Char_t* AliFMDGeometryBuilder::fgkBackName        = "F%dSB";
88 const Char_t* AliFMDGeometryBuilder::fgkTopName         = "F%dSU";
89 const Char_t* AliFMDGeometryBuilder::fgkBeamName        = "F%dSL";
90 const Char_t* AliFMDGeometryBuilder::fgkFlangeName      = "F%dSF";
91 const Char_t* AliFMDGeometryBuilder::fgkFMDDCuName      = "F%cDC";
92 const Char_t* AliFMDGeometryBuilder::fgkFMDDPCBName     = "F%cDP";
93 const Char_t* AliFMDGeometryBuilder::fgkFMDDChipName    = "F%cDI";
94 const Char_t* AliFMDGeometryBuilder::fgkFMDDName        = "F%cDD";
95 const Char_t* AliFMDGeometryBuilder::fgkFMDName         = "F%dM%c";
96
97 //____________________________________________________________________
98 AliFMDGeometryBuilder::AliFMDGeometryBuilder() 
99   : TTask("FMD", "Geomtry builder"),
100     fActiveId(0),
101     fDetailed(kTRUE),
102     fUseAssembly(kTRUE),
103     fSectorOff(0),
104     fModuleOff(0),
105     fRingOff(0),
106     fDetectorOff(0),
107     fSi(0),
108     fC(0),
109     fAl(0),
110     fPCB(0),
111     fChip(0),
112     fAir(0),
113     fPlastic(0),
114     fCopper(0),
115     fSteel(0)
116 {
117   // Default constructor
118   fActiveId.Set(2);
119 }
120
121 //____________________________________________________________________
122 AliFMDGeometryBuilder::AliFMDGeometryBuilder(Bool_t detailed) 
123   : TTask("FMD", "Geometry builder"),
124     fActiveId(0),
125     fDetailed(detailed),
126     fUseAssembly(kTRUE),
127     fSectorOff(0),
128     fModuleOff(0),
129     fRingOff(0),
130     fDetectorOff(0),
131     fSi(0),
132     fC(0),
133     fAl(0),
134     fPCB(0),
135     fChip(0),
136     fAir(0),
137     fPlastic(0),
138     fCopper(0),
139     fSteel(0)
140 {
141   // Normal constructor
142   // 
143   // Parameters: 
144   // 
145   //      fmd           Pointer to AliFMD object 
146   //      detailed      Whether to make a detailed simulation or not 
147   // 
148   fActiveId.Set(2);
149 }
150
151
152 //____________________________________________________________________
153 TGeoVolume*
154 AliFMDGeometryBuilder::RingGeometry(AliFMDRing* r) 
155 {
156   // Setup the geometry of a ring.    The defined TGeoVolume is
157   // returned, and should be used when setting up the rest of the
158   // volumes. 
159   // 
160   // 
161   // Parameters:
162   //
163   //     r              Pointer to ring geometry object 
164   // 
165   // Returns:
166   //    pointer to ring volume 
167   //
168   if (!r) { 
169     AliError("Didn't get a ring object");
170     return 0;
171   }
172   Char_t        id       = r->GetId();
173   const Char_t* lName    = (id == 'i' || id == 'I' ? "inner" : "outer");
174   Double_t      siThick  = r->GetSiThickness();
175   const Int_t   knv      = r->GetNVerticies();
176   TVector2*     a        = r->GetVertex(5);
177   TVector2*     b        = r->GetVertex(3);
178   TVector2*     c        = r->GetVertex(4);
179   Double_t      theta    = r->GetTheta();
180   Double_t      off      = (TMath::Tan(TMath::Pi() * theta / 180) 
181                             * r->GetBondingWidth());
182   Double_t      rmax     = b->Mod();
183   Double_t      rmin     = r->GetLowR();
184   Double_t      pcbThick = r->GetPrintboardThickness();
185   Double_t      cuThick  = r->GetCopperThickness();
186   Double_t      chipThick= r->GetChipThickness();
187   Double_t      modSpace = r->GetModuleSpacing();
188   Double_t      legr     = r->GetLegRadius();
189   Double_t      legl     = r->GetLegLength();
190   Double_t      legoff   = r->GetLegOffset();
191   Int_t         ns       = r->GetNStrips();
192   Double_t      stripoff = a->Mod();
193   Double_t      dstrip   = (rmax - stripoff) / ns;
194   Double_t      space    = r->GetSpacing();
195   TArrayD       xs(knv);
196   TArrayD       ys(knv);
197   for (Int_t i = 0; i < knv; i++) {
198     // Reverse the order 
199     TVector2* vv = r->GetVertex(knv - 1 - i);
200     if (!vv) {
201       AliError(Form("Failed to get vertex # %d", knv - 1 - i));
202       continue;
203     }
204     xs[i] = vv->X();
205     ys[i] = vv->Y();
206   }
207   
208   // Shape of actual sensor 
209   TGeoXtru* sensorShape = new TGeoXtru(2);
210   sensorShape->DefinePolygon(knv, xs.fArray, ys.fArray);
211   sensorShape->DefineSection(0, - siThick/2);
212   sensorShape->DefineSection(1, siThick/2);
213   sensorShape->SetName(Form(fgkSensorName, id));
214   sensorShape->SetTitle(Form("FMD %s Sensor", lName));
215   TGeoVolume* sensorVolume = new TGeoVolume(Form(fgkSensorName, id), 
216                                             sensorShape, fSi);
217   sensorVolume->SetTitle(Form("FMD %s Sensor", lName));
218   sensorVolume->VisibleDaughters(kFALSE);
219   Int_t sid = sensorVolume->GetNumber();
220   fSectorOff   = -1;
221   fModuleOff   = 1;
222   fRingOff     = 2;
223   fDetectorOff = 3;
224   if (fDetailed) {
225     fSectorOff   = 1;
226     fModuleOff   = 4;
227     fRingOff     = 5;
228     fDetectorOff = 6;
229     // Virtual volume shape to divide - This volume is only defined if
230     // the geometry is set to be detailed. 
231     TGeoTubeSeg* activeShape = new TGeoTubeSeg(rmin, rmax, siThick/2, 
232                                                - theta, theta);
233     activeShape->SetName(Form(fgkActiveName, id));
234     activeShape->SetTitle(Form("FMD %s active area", lName));
235     TGeoVolume* activeVolume = new TGeoVolume(Form(fgkActiveName, id),
236                                               activeShape,fSi);
237     activeVolume->SetTitle(Form("FMD %s active area", lName));
238     TGeoVolume* sectorVolume = activeVolume->Divide(Form(fgkSectorName,id), 
239                                                       2, 2, -theta,0,0,"N");
240     sectorVolume->SetTitle(Form("FMD %s sector", lName));
241     TGeoVolume* stripVolume  = sectorVolume->Divide(Form(fgkStripName, id), 
242                                                     1, ns, stripoff, dstrip, 
243                                                     0, "SX");
244     stripVolume->SetTitle(Form("FMD %s strip", lName));
245     sid = stripVolume->GetNumber();
246     sensorVolume->AddNodeOverlap(activeVolume, 0);
247   }
248   
249   switch (id) {
250   case 'i': case 'I': fActiveId[0] = sid; break;
251   case 'o': case 'O': fActiveId[1] = sid; break;
252   }
253
254   // Shape of Printed circuit Board 
255   for (Int_t i = 0;       i < knv / 2; i++) ys[i] -= off;
256   for (Int_t i = knv / 2; i < knv;     i++) ys[i] += off;
257   TGeoXtru* pcbShape         = new TGeoXtru(2);
258   pcbShape->DefinePolygon(knv, xs.fArray, ys.fArray);
259   pcbShape->DefineSection(0, - pcbThick/2);
260   pcbShape->DefineSection(1, pcbThick/2);
261   pcbShape->SetName(Form(fgkPCBName, id));
262   pcbShape->SetTitle(Form("FMD %s hybrid PCB", lName));
263   TGeoVolume* pcbVolume      = new TGeoVolume(Form(fgkPCBName, id), 
264                                               pcbShape, fPCB);
265   pcbVolume->SetTitle(Form("FMD %s hybrid PCB", lName));
266
267   // Copper layer
268   TGeoXtru* cuShape       = new TGeoXtru(2);
269   cuShape->DefinePolygon(6, xs.fArray, ys.fArray);
270   cuShape->DefineSection(0, - cuThick/2);
271   cuShape->DefineSection(1, cuThick/2);
272   cuShape->SetTitle(Form("FMD %s hybrid copper", lName));
273   TGeoVolume* cuVolume    = new TGeoVolume(Form(fgkCuName,id),cuShape,fCopper);
274   cuVolume->SetTitle(Form("FMD %s hybrid copper", lName));
275
276   // Chip layer
277   TGeoXtru*   chipShape   = new TGeoXtru(2);
278   chipShape->DefinePolygon(6, xs.fArray, ys.fArray);
279   chipShape->DefineSection(0, - chipThick/2);
280   chipShape->DefineSection(1, chipThick/2);
281   chipShape->SetTitle(Form("FMD %s hybrid chip", lName));
282   TGeoVolume* chipVolume = new TGeoVolume(Form(fgkChipName,id),
283                                           chipShape,fChip);
284   chipVolume->SetTitle(Form("FMD %s hybrid chip", lName));
285
286   // Short leg shape 
287   TGeoTube*   shortLegShape  = new TGeoTube(0, legr, legl / 2);
288   shortLegShape->SetName(Form(fgkShortLegName, id));
289   shortLegShape->SetTitle(Form("FMD %s short support foot", lName));
290   TGeoVolume* shortLegVolume = new TGeoVolume(Form(fgkShortLegName, id), 
291                                               shortLegShape, fCopper);
292   shortLegVolume->SetTitle(Form("FMD %s short support foot", lName));
293   // Long leg shape
294   TGeoTube*   longLegShape   = new TGeoTube(0, legr, (legl + modSpace) / 2);
295   longLegShape->SetName(Form(fgkLongLegName, id));
296   longLegShape->SetTitle(Form("FMD %s long support foot", lName));
297   TGeoVolume* longLegVolume  = new TGeoVolume(Form(fgkLongLegName, id), 
298                                               longLegShape, fCopper);
299   longLegVolume->SetTitle(Form("FMD %s long support foot", lName));
300   
301   
302   // Back container volume 
303   TGeoVolume* backVolume     = new TGeoVolumeAssembly(Form(fgkBackVName, id));
304   backVolume->SetTitle(Form("FMD %s back module", lName));
305   Double_t x = 0;
306   Double_t y = 0;
307   Double_t z = siThick / 2;
308   backVolume->AddNode(sensorVolume, 0, new TGeoTranslation(x, y, z));
309   z          += siThick / 2 + space + pcbThick / 2;
310   backVolume->AddNode(pcbVolume, 0, new TGeoTranslation(x,y,z));
311   z          += (pcbThick + cuThick) / 2;
312   backVolume->AddNode(cuVolume, 0, new TGeoTranslation(0, 0, z));
313   z          += (cuThick + chipThick) / 2;
314   backVolume->AddNode(chipVolume, 0, new TGeoTranslation(0, 0, z));
315   x          =  a->X() + legoff + legr;
316   y          =  0;
317   z          += pcbThick / 2 + legl / 2;
318   backVolume->AddNode(shortLegVolume, 0, new TGeoTranslation(x,y,z));
319   x          =  c->X();
320   y          =  c->Y() - legoff - legr - off;
321   backVolume->AddNode(shortLegVolume, 1, new TGeoTranslation(x,y,z));
322   y          =  -y;
323   backVolume->AddNode(shortLegVolume, 2, new TGeoTranslation(x,y,z));
324
325   // Front container volume 
326   TGeoVolume* frontVolume    = new TGeoVolumeAssembly(Form(fgkFrontVName, id));
327   frontVolume->SetTitle(Form("FMD %s front module", lName));
328   x         =  0;
329   y         =  0;
330   z         = siThick / 2;
331   frontVolume->AddNode(sensorVolume, 0, new TGeoTranslation(x, y, z));
332   z          += siThick / 2 + space + pcbThick / 2;
333   frontVolume->AddNode(pcbVolume, 0, new TGeoTranslation(x,y,z));
334   z          += (pcbThick + cuThick) / 2;
335   frontVolume->AddNode(cuVolume, 0, new TGeoTranslation(0, 0, z));
336   z          += (cuThick + chipThick) / 2;
337   frontVolume->AddNode(chipVolume, 0, new TGeoTranslation(0, 0, z));
338   x         =  a->X() + legoff + legr;
339   y         =  0;
340   z         += pcbThick / 2 + (legl + modSpace)/ 2;
341   frontVolume->AddNode(longLegVolume, 0, new TGeoTranslation(x,y,z));
342   x         =  c->X();
343   y         =  c->Y() - legoff - legr - off;
344   frontVolume->AddNode(longLegVolume, 1, new TGeoTranslation(x,y,z));
345   y         =  -y;
346   frontVolume->AddNode(longLegVolume, 2, new TGeoTranslation(x,y,z));
347
348
349   // FMDD 
350   Double_t ddlr = r->GetFMDDLowR();
351   Double_t ddhr = r->GetFMDDHighR();
352   Double_t ddpt = r->GetFMDDPrintboardThickness();
353   Double_t ddct = r->GetFMDDCopperThickness();
354   Double_t ddit = r->GetFMDDChipThickness();
355   Double_t ddt  = ddpt + ddct + ddit;
356   
357   TString    pcbName(Form(fgkFMDDPCBName, id));
358   TString    cuName(Form(fgkFMDDCuName, id));
359   TString    chipName(Form(fgkFMDDChipName, id));
360   new TGeoTubeSeg(Form("%s_inner", pcbName.Data()),  ddlr, ddhr, ddpt/2,0,180);
361   new TGeoTubeSeg(Form("%s_inner", cuName.Data()),   ddlr, ddhr, ddct/2,0,180);
362   new TGeoTubeSeg(Form("%s_inner", chipName.Data()), ddlr, ddhr, ddit/2,0,180);
363   
364   Double_t clipWX = 0;
365   Double_t clipWY = 0;
366   Double_t clipY  = 1;
367   
368   if (id == 'I' || id == 'i') { 
369     clipWX = ddhr;
370     clipWY = ddhr/2;
371   }
372   else { 
373     clipWX = ddlr+3;
374     clipWY = ddhr/2;
375   }
376   
377   new TGeoBBox(Form("%s_clip",  pcbName.Data()), clipWX, clipWY, ddpt);
378   new TGeoBBox(Form("%s_clip",  cuName.Data()),  clipWX, clipWY, ddct);
379   new TGeoBBox(Form("%s_clip",  chipName.Data()),clipWX, clipWY, ddit);
380   TGeoTranslation* trans = new TGeoTranslation(Form("%s_trans",
381                                                     pcbName.Data()), 
382                                                0, clipWY+clipY, 0);
383   trans->RegisterYourself();
384   TGeoShape* fmddPcbShape = 
385     new TGeoCompositeShape(pcbName.Data(), 
386                            Form("%s_inner*%s_clip:%s_trans",
387                                 pcbName.Data(), 
388                                 pcbName.Data(), 
389                                 pcbName.Data())); 
390   TGeoShape* fmddCuShape = 
391     new TGeoCompositeShape(cuName.Data(), 
392                            Form("%s_inner*%s_clip:%s_trans",
393                                 cuName.Data(), 
394                                 cuName.Data(), 
395                                 pcbName.Data()));
396   TGeoShape* fmddChipShape = 
397     new TGeoCompositeShape(chipName.Data(), 
398                            Form("%s_inner*%s_clip:%s_trans",
399                                 chipName.Data(), 
400                                 chipName.Data(), 
401                                 pcbName.Data()));
402   fmddPcbShape->SetTitle(Form("FMD %s digitiser PCB", lName));
403   fmddCuShape->SetTitle(Form("FMD %s digitiser copper", lName));
404   fmddChipShape->SetTitle(Form("FMD %s digitiser chip", lName));
405
406   TGeoVolume*  fmddPcbVolume = new TGeoVolume(Form(fgkFMDDPCBName, id),
407                                               fmddPcbShape, fPCB);
408   TGeoVolume*  fmddCuVolume  = new TGeoVolume(Form(fgkFMDDCuName, id),
409                                               fmddCuShape, fCopper);
410   TGeoVolume*  fmddChipVolume= new TGeoVolume(Form(fgkFMDDChipName, id),
411                                               fmddChipShape, fChip);
412   fmddPcbVolume->SetTitle(Form("FMD %s digitiser PCB", lName));
413   fmddCuVolume->SetTitle(Form("FMD %s digitiser copper", lName));
414   fmddChipVolume->SetTitle(Form("FMD %s digitiser chip", lName));
415
416   // Half ring mother volumes. 
417   TGeoVolume* ringTopVolume = new TGeoVolumeAssembly(Form(fgkRingTopName,id));
418   TGeoVolume* ringBotVolume = new TGeoVolumeAssembly(Form(fgkRingBotName,id));
419   TGeoVolume* halfRing      = ringTopVolume;
420   ringTopVolume->SetTitle(Form("FMD %s top half-ring", lName));
421   ringBotVolume->SetTitle(Form("FMD %s bottom half-ring", lName));
422   
423   // Adding modules to half-rings
424   Int_t    nmod =  r->GetNModules();
425   AliFMDDebug(10, ("making %d modules in ring %c", nmod, id));
426   for (Int_t i = 0; i < nmod; i++) {
427     if (i == nmod / 2) halfRing = ringBotVolume;
428     Bool_t      front =  (i % 2 == 0);
429     TGeoVolume* vol   =  (front ? frontVolume : backVolume);
430     // vol->AddNode(sensorVolume, i, new TGeoTranslation(0,0,siThick/2));
431     Double_t    z1    =  (i % 2) * modSpace;
432     Double_t    th    =  (2 * i + 1) * theta;
433     TGeoMatrix* mat1  =  new TGeoCombiTrans(0,0,z1,0); 
434     mat1->RotateZ(th);
435     mat1->SetName(Form("FMD%c_module_%02d", id, i));
436     mat1->SetTitle(Form("FMD %s module %2d matrix", lName, i));
437     halfRing->AddNode(vol, i, mat1);
438 #if 0
439     Double_t    z2    =  z1 + siThick / 2 + space;
440     Double_t    th    =  (2 * i + 1) * theta;
441     AliFMDDebug(20, ("Placing copy %d of %s and %s in %s at z=%f and %f, "
442                       "and theta=%f", i, sensorVolume->GetName(), 
443                       vol->GetName(), halfRing->GetName(), z1, z2, th));
444     TGeoMatrix* mat1  =  new TGeoCombiTrans(0,0,z1,0); 
445     mat1->RotateZ(th);
446     halfRing->AddNode(sensorVolume, i, mat1);
447     TGeoMatrix* mat2  =  new TGeoCombiTrans(0,0,z2,0); 
448     mat2->RotateZ(th);
449     halfRing->AddNode(vol, i, mat2);
450 #endif
451   }
452
453   // Add the FMDD 
454   Double_t zi = r->GetFullDepth() - ddt;
455   Int_t    n  = 2;
456   for (Int_t i = 0; i  < n; i++) {
457     halfRing             = (i == 0 ? ringTopVolume : ringBotVolume);
458     Double_t      phi    = 360. / n * i;
459     TGeoRotation* rot    = new TGeoRotation(Form("FMDD%c rotation %d", id, i));
460     rot->RotateZ(phi);
461     rot->SetTitle(Form("FMD %s digitiser rotation %2d", lName, i));
462     z         =  zi + ddpt / 2;
463     halfRing->AddNode(fmddPcbVolume, i, new TGeoCombiTrans(0,0,z,rot));
464     z          += (ddpt + ddct) / 2;
465     halfRing->AddNode(fmddCuVolume, i, new TGeoCombiTrans(0,0,z,rot));
466     z          += (ddct + ddit) / 2;
467     halfRing->AddNode(fmddChipVolume, i, new TGeoCombiTrans(0,0,z,rot));
468   }
469   
470
471   return 0;
472 }
473
474 //____________________________________________________________________
475 TGeoShape*
476 AliFMDGeometryBuilder::HoneycombShape(Int_t id, Char_t ring,
477                                       double r1, double r2, 
478                                       double w, double t, double c)
479 {
480   // Make a honey comb shape from passed parameters.
481   // Parameters: 
482   //   id       Detector identifier (1,2, or 3)
483   //   ring     Ring identifier ('I' or 'O')
484   //   r1       Inner radius
485   //   r2       Outer radius
486   //   w        width 
487   //   t        Thickness of material 
488   //   c        Clearing from horizontal. 
489   // Return 
490   //   Pointer to newly allocated composite shape. 
491   TString      form  = Form("FMD%d%c_%%c_%%c", id, ring);
492   double       a1    = TMath::ATan2(c, r1) * 180  / TMath::Pi();
493
494   TString      fn    = Form(form.Data(),'F','1');
495   TString      bn    = Form(form.Data(),'B','1');
496   TString      cn    = Form(form.Data(),'C','O');
497   TString      in    = Form(form.Data(),'R','I');
498   TString      on    = Form(form.Data(),'R','O');
499   TString      en    = Form(form.Data(),'E','X');
500   double       y     = c;
501   double       x     = r1 * TMath::Cos(TMath::Pi()*a1/180);
502   new TGeoTubeSeg(fn.Data(),r1,r2,t/2,0,180);
503   new TGeoTubeSeg(bn.Data(),r1,r2,t/2,0,180);
504   new TGeoBBox(cn.Data(),(r2-r1)/2,t/2,w/2);
505   new TGeoTubeSeg(in.Data(),r1,r1+t,w/2,0,180);
506   new TGeoTubeSeg(on.Data(),r2-t,r2,w/2,0,180);
507   new TGeoBBox(en.Data(),r2+.005,c/2+.005,w/2+.005);
508     
509   TString          ftn = Form(form.Data(),'F','T');
510   TString          btn = Form(form.Data(),'F','B');
511   TString          ltn = Form(form.Data(),'C','L');
512   TString          rtn = Form(form.Data(),'C','R');
513   TString          etn = Form(form.Data(),'E','X');
514   (new TGeoTranslation(ftn.Data(),0,0,+w/2-t/2))->RegisterYourself();
515   (new TGeoTranslation(btn.Data(),0,0,-w/2+t/2))->RegisterYourself();
516   (new TGeoTranslation(ltn.Data(),-(x+(r2-r1)/2), y+t/2,0))->RegisterYourself();
517   (new TGeoTranslation(rtn.Data(),(x+(r2-r1)/2), y+t/2,0))->RegisterYourself();
518   (new TGeoTranslation(etn.Data(),0, c/2,0))->RegisterYourself();
519   
520   TString comp(Form("(%s:%s+%s:%s+%s+%s+%s:%s+%s:%s)-%s:%s", 
521                     fn.Data(),ftn.Data(),
522                     bn.Data(),btn.Data(),
523                     in.Data(),on.Data(),
524                     cn.Data(),ltn.Data(),
525                     cn.Data(),rtn.Data(),
526                     en.Data(),etn.Data()));
527   TGeoCompositeShape* shape = new TGeoCompositeShape(comp.Data());
528   shape->SetName(Form(fgkHCName,id,ring));
529   shape->SetTitle(Form("FMD%d%c Honeycomb shape", id, ring));
530   return shape;
531 }
532
533
534 //____________________________________________________________________
535 TGeoVolume*
536 AliFMDGeometryBuilder::DetectorGeometry(AliFMDDetector* d, 
537                                         TGeoVolume* topMother, 
538                                         TGeoVolume* botMother, 
539                                         Double_t    zMother, 
540                                         TGeoVolume* innerTop, 
541                                         TGeoVolume* innerBot, 
542                                         TGeoVolume* outerTop, 
543                                         TGeoVolume* outerBot) 
544 {
545   // Common stuff for setting up the FMD1, FMD2, and FMD3 geometries.
546   // This includes putting the Honeycomb support plates and the rings
547   // into the mother volumes.   
548   // 
549   // Parameeters:
550   //    d         The detector geometry to use 
551   //    mother    The mother volume of the detector 
552   //    zmother   The midpoint in global coordinates of detector vol.
553   //    inner     Pointer to inner ring volume 
554   //    outer     Pointer to outer ring volume
555   //
556   // Returns:
557   //    Pointer to mother (detector volume) 
558   // 
559   if (!d) return 0;
560   // Loop over the defined rings 
561   for (int i = 0; i < 2; i++) {
562     AliFMDRing* r     = 0;
563     Double_t    lowr  = 0;
564     Double_t    highr = 0;
565     Double_t    rz    = 0;
566     TGeoVolume* tvol  = 0;
567     TGeoVolume* bvol  = 0;
568     switch (i) {
569     case 0: 
570       r      = d->GetInner();
571       lowr   = d->GetInnerHoneyLowR();
572       highr  = d->GetInnerHoneyHighR();
573       rz     = d->GetInnerZ();
574       tvol   = innerTop;
575       bvol   = innerBot;
576       break;
577     case 1: 
578       r      = d->GetOuter();
579       lowr   = d->GetOuterHoneyLowR();
580       highr  = d->GetOuterHoneyHighR();
581       rz     = d->GetOuterZ();
582       tvol   = outerTop;
583       bvol   = outerBot;
584       break;
585     }
586     if (!r) continue;
587     Char_t   c       = r->GetId();
588     Int_t    id      = d->GetId();
589     Double_t hcThick = r->GetHoneycombThickness();
590     Double_t alThick = r->GetAlThickness();
591     Double_t z       = TMath::Abs(rz - zMother);
592
593     // Place ring in mother volume
594     // TGeoMatrix*matrix=new TGeoTranslation(Form("FMD%d%c trans",id,c),0,0,0);
595     AliFMDDebug(1, ("Placing volumes %s and %s in %s and %s at z=%f", 
596                      tvol->GetName(), bvol->GetName(), 
597                      topMother->GetName(), botMother->GetName(), z));
598     topMother->AddNode(tvol, Int_t(c), new TGeoTranslation(0,0,z));
599     botMother->AddNode(bvol, Int_t(c), new TGeoTranslation(0,0,z));
600
601     // Honeycomp 
602     TGeoShape*   hcSha = HoneycombShape(id, c, lowr, highr, hcThick, alThick);
603     TGeoVolume*  hcVol = new TGeoVolume(Form(fgkHCName,id,c),hcSha,fAl);
604     hcVol->SetTitle(Form("FMD%d%c honeycomb shell", id, c));
605     
606     z += (r->GetSiThickness() + 
607           r->GetSpacing() + 
608           r->GetPrintboardThickness() + 
609           r->GetCopperThickness() + 
610           r->GetChipThickness() + 
611           r->GetModuleSpacing() +
612           r->GetLegLength() + 
613           r->GetHoneycombThickness() + 
614           r->GetFMDDPrintboardThickness() - 
615           hcThick / 2); 
616
617     AliFMDDebug(15, ("Placing a copy of %s in %s and %s at z=%f", 
618                       hcVol->GetName(), topMother->GetName(), 
619                       botMother->GetName(), z));
620     // Add to top 
621     topMother->AddNode(hcVol, 0, new TGeoTranslation(0, 0, z));
622
623     // Add to bottom
624     TGeoMatrix*   bhcMatrix = new TGeoCombiTrans(0,0,z,0);
625     bhcMatrix->SetName(Form("FMD%d%c_honeycomp", id, c));
626     bhcMatrix->SetTitle(Form("FMD%d%c honeycomp", id, c));
627     bhcMatrix->RotateZ(180);
628     botMother->AddNode(hcVol, 1, bhcMatrix);
629   }
630   return 0;
631 }
632
633 //____________________________________________________________________
634 TGeoVolume*
635 AliFMDGeometryBuilder::FMD1Geometry(AliFMD1* fmd1, 
636                                     TGeoVolume* innerTop, 
637                                     TGeoVolume* innerBot) 
638 {
639   // Setup the FMD1 geometry.  The FMD1 only has one ring, and no
640   // special support as it is at the momement. 
641   // 
642   // See also AliFMDGeometryBuilder::DetectorGeometry 
643   // 
644   if (!fmd1 || !innerTop || !innerBot) return 0;
645   AliFMDRing* r             = fmd1->GetInner();
646   Double_t    z             = fmd1->GetInnerZ();  
647   Double_t    disce         = 2;
648   Double_t    backlr        = fmd1->GetInnerHoneyHighR();
649   Double_t    backhr        = fmd1->GetInnerHoneyHighR()+5;
650   Double_t    backth        = 0.2;
651   Double_t    toplr         = r->GetLowR();
652   Double_t    tophr         = fmd1->GetInnerHoneyHighR()+disce;
653   Double_t    wallbh        = (r->GetFullDepth() + disce);
654   Double_t    wallth        = wallbh+0.1;
655   
656   TGeoVolume* fmd1TopVolume = new TGeoVolumeAssembly(Form(fgkFMDName, 
657                                                           fmd1->GetId(), 'T'));
658   fmd1TopVolume->SetTitle("FMD1 top half");
659   TGeoVolume* fmd1BotVolume = new TGeoVolumeAssembly(Form(fgkFMDName, 
660                                                           fmd1->GetId(), 'B'));
661   fmd1BotVolume->SetTitle("FMD1 bottom half");
662   
663   // Basic detector geometry 
664   DetectorGeometry(fmd1, fmd1TopVolume, fmd1BotVolume, z, 
665                    innerTop, innerBot, 0, 0);
666
667
668   // Back
669   TGeoTubeSeg* backShape  = new TGeoTubeSeg(backlr, backhr, backth / 2, 0, 180);
670   TGeoTubeSeg* wallbShape = new TGeoTubeSeg(backlr, backlr + backth, 
671                                             wallbh/2, 0, 180);
672   TGeoTubeSeg* topShape   = new TGeoTubeSeg(toplr, tophr, backth / 2, 0, 180);
673   TGeoTubeSeg* walltShape = new TGeoTubeSeg(tophr, tophr + backth, 
674                                             wallth/2, 0, 180);
675   TGeoVolume*  backVolume = new TGeoVolume(Form(fgkBackName, fmd1->GetId()), 
676                                            backShape, fC);
677   TGeoVolume*  wallbVolume= new TGeoVolume(Form(fgkFlangeName, fmd1->GetId()), 
678                                            wallbShape, fC);
679   TGeoVolume*  topVolume  = new TGeoVolume(Form(fgkTopName, fmd1->GetId()), 
680                                            topShape, fC);
681   TGeoVolume*  walltVolume= new TGeoVolume(Form(fgkBeamName, fmd1->GetId()), 
682                                            walltShape, fC);
683   backShape->SetName(Form(fgkBackName, fmd1->GetId()));
684   wallbShape->SetName(Form(fgkFlangeName, fmd1->GetId()));
685   topShape->SetName(Form(fgkTopName, fmd1->GetId()));
686   walltShape->SetName(Form(fgkBeamName, fmd1->GetId()));
687   backShape->SetTitle("FMD1 back saucer rim");
688   wallbShape->SetTitle("FMD1 back saucer wall");
689   topShape->SetTitle("FMD1 top lid");
690   walltShape->SetTitle("FMD1 top lid wall");
691   backVolume->SetFillColor(kGray);
692   topVolume->SetFillColor(kGray);
693   wallbVolume->SetFillColor(kGray);
694   walltVolume->SetFillColor(kGray);
695   backVolume->SetTitle("FMD1 back saucer rim");
696   wallbVolume->SetTitle("FMD1 back saucer wall");
697   topVolume->SetTitle("FMD1 top lid");
698   walltVolume->SetTitle("FMD1 top lid wall");
699   
700   // Place volumes
701   Double_t zb = TMath::Abs(fmd1->GetInnerZ() - z);
702   Double_t zi = zb;
703   Int_t    n  = 2;
704   
705   // Place top cover
706   zi -= disce / 2 + backth / 2;
707   zb =  zi;
708   for (Int_t i = 0; i  < 2; i++) {
709     TGeoVolume*   mother = (i == 0 ? fmd1TopVolume : fmd1BotVolume);
710     Double_t      phi    = 360. / n * i;
711     TGeoRotation* rot    = new TGeoRotation(Form("FMD1 top rotation %d",i));
712     rot->RotateZ(phi);
713     TGeoMatrix* matrix   = new TGeoCombiTrans(Form("FMD1 top wall trans %d", i),
714                                               0, 0, zi, rot);
715     mother->AddNode(topVolume, i, matrix);    
716   }
717   // Place outer wall
718   zi += wallth / 2 + backth / 2;
719   for (Int_t i = 0; i  < 2; i++) {
720     TGeoVolume*   mother = (i == 0 ? fmd1TopVolume : fmd1BotVolume);
721     Double_t      phi    = 360. / n * i;
722     TGeoRotation* rot    = new TGeoRotation(Form("FMD1 outer wall rotation %d",
723                                                  i));
724     rot->RotateZ(phi);
725     TGeoMatrix* matrix   = new TGeoCombiTrans(Form("FMD1 outer wall trans %d",
726                                                    i), 0, 0, zi, rot);
727     mother->AddNode(walltVolume, i, matrix);    
728   }
729   // Place back
730   zi += wallth / 2 + backth / 2; // + disce / 2;
731   for (Int_t i = 0; i  < 2; i++) {
732     TGeoVolume*   mother = (i == 0 ? fmd1TopVolume : fmd1BotVolume);
733     Double_t      phi    = 360. / n * i;
734     TGeoRotation* rot    = new TGeoRotation(Form("FMD1 back rotation %d", i));
735     rot->RotateZ(phi);
736     TGeoMatrix* matrix   = new TGeoCombiTrans(Form("FMD1 back trans %d", i),
737                                              0, 0, zi, rot);
738     mother->AddNode(backVolume, i, matrix);    
739   }
740   // Place inner wall
741   zi -= wallbh / 2 + backth / 2; // + disce / 2;
742   for (Int_t i = 0; i  < 2; i++) {
743     TGeoVolume*   mother = (i == 0 ? fmd1TopVolume : fmd1BotVolume);
744     Double_t      phi    = 360. / n * i;
745     TGeoRotation* rot    = new TGeoRotation(Form("FMD1 inner wall rotation %d",
746                                                  i)); 
747     rot->RotateZ(phi);
748     TGeoMatrix*   matrix = new TGeoCombiTrans(Form("FMD1 inner wall trans %d", 
749                                                    i), 0, 0, zi, rot);
750     mother->AddNode(wallbVolume, i, matrix);    
751   }
752
753
754   // Must add this after filling the assembly.
755   TGeoVolume* top    = gGeoManager->GetVolume("ALIC");
756   // TGeoMatrix* matrix = new TGeoTranslation("FMD1 trans", 0, 0, z);
757   TGeoRotation* rot = new TGeoRotation("FMD1 rotatation");
758   rot->RotateZ(-90);
759   TGeoMatrix* matrix = new TGeoCombiTrans("FMD1 trans", 0, 0, z, rot);
760   AliFMDDebug(5, ("Placing volumes %s and %s in ALIC at z=%f", 
761                    fmd1TopVolume->GetName(), fmd1BotVolume->GetName(), z));
762   top->AddNode(fmd1TopVolume, fmd1->GetId(), matrix);
763   top->AddNode(fmd1BotVolume, fmd1->GetId(), matrix);
764
765   return 0;
766 }
767
768 //____________________________________________________________________
769 TGeoVolume*
770 AliFMDGeometryBuilder::FMD2Geometry(AliFMD2* fmd2, 
771                                     TGeoVolume* innerTop, 
772                                     TGeoVolume* innerBot, 
773                                     TGeoVolume* outerTop,
774                                     TGeoVolume* outerBot) 
775 {
776   // Setup the FMD2 geometry.  The FMD2 has no
777   // special support as it is at the momement. 
778   // 
779   // See also AliFMDGeometryBuilder::DetectorGeometry 
780   // 
781   if (!fmd2 || !innerTop || !innerBot || !outerTop || !outerBot) return 0;
782   AliFMDRing* r             = fmd2->GetOuter();
783   Double_t    z             = fmd2->GetOuterZ();  
784   Double_t    framelr       = fmd2->GetOuterHoneyHighR()+0.5;
785   Double_t    framehr       = fmd2->GetOuterHoneyHighR()+1.8;
786   Double_t    framelz       = -.5;
787   Double_t    framehz       = (fmd2->GetInnerZ()-z) + r->GetFullDepth() + .5;
788   Double_t    framel        = framehz - framelz;
789   Double_t    coverlr       = fmd2->GetInner()->GetLowR()+1;
790   Double_t    backth        = 0.05;
791
792   TGeoVolume* fmd2TopVolume = new TGeoVolumeAssembly(Form(fgkFMDName, 
793                                                           fmd2->GetId(), 'T'));
794   TGeoVolume* fmd2BotVolume = new TGeoVolumeAssembly(Form(fgkFMDName, 
795                                                           fmd2->GetId(), 'B'));
796   fmd2TopVolume->SetTitle("FMD2 top half");
797   fmd2BotVolume->SetTitle("FMD2 bottom half");
798   
799   DetectorGeometry(fmd2, fmd2TopVolume, fmd2BotVolume, z, 
800                    innerTop, innerBot, outerTop, outerBot);
801
802   TGeoShape*  cylinderShape   = new TGeoTubeSeg(framelr,framehr,framel/2,0,180);
803   TGeoVolume* cylinderVolume  = new TGeoVolume(Form(fgkBackName, fmd2->GetId()),
804                                                cylinderShape, fC);
805   TGeoShape*  coverShape      = new TGeoTubeSeg(coverlr,framehr,backth/2,0,180);
806   TGeoVolume* coverVolume     = new TGeoVolume(Form(fgkTopName, fmd2->GetId()), 
807                                                coverShape, fC);
808   cylinderShape->SetName(Form(fgkBackName, fmd2->GetId()));
809   cylinderShape->SetTitle("FMD2 cylinder");
810   cylinderVolume->SetTitle("FMD2 cylinder");
811   cylinderVolume->SetTransparency(63);
812   coverShape->SetName(Form(fgkTopName, fmd2->GetId()));
813   coverShape->SetTitle("FMD2 cover");
814   coverVolume->SetTitle("FMD2 cover");
815   coverVolume->SetTransparency(63);
816   
817   for (Int_t i = 0; i  < 2; i++) {
818     TGeoVolume*   mother = (i == 0 ? fmd2TopVolume : fmd2BotVolume);
819     
820     Double_t      phi    = 360. / 2 * i;
821     TGeoRotation* rot    = new TGeoRotation(Form("FMD2 support rot %d",i)); 
822     rot->RotateZ(phi);
823     TGeoMatrix*   matrix = new TGeoCombiTrans(Form("FMD2 cyl trans %d", i),
824                                               0, 0, framelz+framel/2, rot);
825     mother->AddNode(cylinderVolume, i, matrix);    
826     matrix               = new TGeoCombiTrans(Form("FMD2 fcov trans %d", i),
827                                               0, 0, framelz-backth/2, rot);
828     mother->AddNode(coverVolume, 2*i+0, matrix);    
829     matrix               = new TGeoCombiTrans(Form("FMD2 bcov trans %d", i),
830                                               0, 0, framelz+framel+backth/2, 
831                                               rot);
832     mother->AddNode(coverVolume, 2*i+1, matrix);    
833   }
834
835
836   Double_t    f1l           = 10;
837   Double_t    f1w           = 6;
838   Double_t    f1d           = 1;
839   
840   TGeoBBox*   flange1Shape  = new TGeoBBox(f1l/2, f1w/2, f1d/2);
841   TGeoVolume* flange1Volume = new TGeoVolume(Form(fgkFlangeName, fmd2->GetId()),
842                                              flange1Shape, fAl);
843   TGeoBBox*   flange2Shape  = new TGeoBBox(f1w/2, f1d/2, (framel+backth)/2);
844   TGeoVolume* flange2Volume = new TGeoVolume(Form("F%dSG", fmd2->GetId()),
845                                              flange2Shape, fAl);
846   flange1Shape->SetName(Form(fgkFlangeName, fmd2->GetId()));
847   flange1Shape->SetTitle("FMD2 vertical flange");
848   flange1Volume->SetTitle("FMD2 vertical flange");
849   flange2Shape->SetName(Form("F%dSG", fmd2->GetId()));
850   flange2Shape->SetTitle("FMD2 horizontal flange");
851   flange2Volume->SetTitle("FMD2 horizontal flange ");
852   
853   flange1Volume->SetTransparency(42);
854   for (Int_t i = 0; i  < 4; i++) {
855     TGeoVolume*   mother = (i < 2 ? fmd2TopVolume : fmd2BotVolume);
856     
857     Double_t      phi    = 360. / 4 * i - 45;
858     Double_t      rphi   = TMath::Pi()*phi/180;
859     Double_t      x      = (framelr + f1l/2) * TMath::Sin(rphi);
860     Double_t      y      = (framelr + f1l/2) * TMath::Cos(rphi);
861     TGeoRotation* rot    = new TGeoRotation(Form("FMD2 support rot %d",i)); 
862     rot->RotateZ(phi);
863     TGeoMatrix*   matrix = new TGeoCombiTrans(Form("FMD2 flange 1 trans %d", i),
864                                               x,y, framelz-backth-f1d/2, rot);
865     mother->AddNode(flange1Volume, 2*i+0, matrix);    
866     matrix               = new TGeoCombiTrans(Form("FMD2 flange 2 trans %d", i),
867                                               x,y,framelz+framel+backth+f1d/2, 
868                                               rot);
869     mother->AddNode(flange1Volume, 2*i+1, matrix);    
870     Double_t x1 = x - (f1w-f1d) / 2 * TMath::Cos(rphi); 
871     Double_t y1 = y + (f1w-f1d) / 2 * TMath::Sin(rphi);
872     matrix               = new TGeoCombiTrans(Form("FMD2 flange 3 trans %d", i),
873                                               x1,y1,framelz+framel/2, rot);
874     mother->AddNode(flange2Volume, 2*i+0, matrix);    
875     Double_t x2 = x + (f1w-f1d) / 2 * TMath::Cos(rphi); 
876     Double_t y2 = y - (f1w-f1d) / 2 * TMath::Sin(rphi);
877     matrix               = new TGeoCombiTrans(Form("FMD2 flange 4 trans %d", i),
878                                               x2,y2,framelz+framel/2, rot);
879     mother->AddNode(flange2Volume, 2*i+1, matrix);    
880   }
881   
882   // Must be done after filling the assemblies 
883   TGeoVolume* top = gGeoManager->GetVolume("ALIC");
884   TGeoMatrix* matrix = new TGeoTranslation("FMD2 trans", 0, 0, z);
885   AliFMDDebug(5, ("Placing volumes %s and %s in ALIC at z=%f", 
886                    fmd2TopVolume->GetName(), fmd2BotVolume->GetName(), z));
887   top->AddNode(fmd2TopVolume, fmd2->GetId(), matrix);
888   top->AddNode(fmd2BotVolume, fmd2->GetId(), matrix);
889
890
891   return 0;
892 }
893   
894 #if 1
895 //____________________________________________________________________
896 TGeoVolume*
897 AliFMDGeometryBuilder::FMD3Geometry(AliFMD3* fmd3, 
898                                     TGeoVolume* innerTop, 
899                                     TGeoVolume* innerBot, 
900                                     TGeoVolume* outerTop,
901                                     TGeoVolume* outerBot) 
902 {
903   // Setup the FMD3 geometry.  The FMD2 has a rather elaborate support
904   // structure, as the support will also support the vacuum
905   // beam-pipe. 
906   // 
907   // See also AliFMDGeometryBuilder::DetectorGeometry 
908   // 
909   if (!fmd3 || !innerTop || !innerBot || !outerTop || !outerBot) return 0;
910
911   //__________________________________________________________________
912   // Basic detector set-up.
913   TGeoVolume* fmd3TopVolume = new TGeoVolumeAssembly(Form(fgkFMDName, 
914                                                           fmd3->GetId(), 'T'));
915   TGeoVolume* fmd3BotVolume = new TGeoVolumeAssembly(Form(fgkFMDName, 
916                                                           fmd3->GetId(), 'B'));
917   fmd3TopVolume->SetTitle("FMD3 top half");
918   fmd3BotVolume->SetTitle("FMD3 bottom half");
919   DetectorGeometry(fmd3, fmd3TopVolume, fmd3BotVolume, fmd3->GetInnerZ(), 
920                    innerTop, innerBot, outerTop, outerBot);
921
922   //__________________________________________________________________
923   // Mother for all support material
924   TGeoVolumeAssembly* support = new TGeoVolumeAssembly("F3SU");
925   support->SetTitle("FMD3 support");
926
927   //__________________________________________________________________
928   // Base of cone
929   const TObjArray& radii    = fmd3->ConeRadii();
930   Int_t            nRadii   = radii.GetEntriesFast();
931   TGeoPcon*        coneBase = new TGeoPcon("FMD3_cone_base", 0., 180., nRadii);
932   TVector3*        r5       = 0;
933   TVector3*        r4       = 0;
934   for (Int_t i = 0; i < nRadii; i++) { 
935     TVector3* v = static_cast<TVector3*>(radii.At(i));
936     coneBase->DefineSection(i, v->X(), v->Y(), v->Z());
937     if      (i == 5) r5 = v;
938     else if (i == 4) r4 = v;
939   }
940   TString          coneComb("(FMD3_cone_base");
941
942   //__________________________________________________________________
943   // Flanges 
944   double    flangeDepth    = fmd3->GetFlangeDepth() / 2;
945   double    flangeLength   = fmd3->GetFlangeLength() / 2;
946   double    flangeWidth    = fmd3->GetFlangeWidth() / 2;
947   new TGeoBBox("FMD3_flange_base", flangeLength, flangeWidth, flangeDepth);
948
949   // Fiducial holes 
950   const TObjArray& fiducialHoles  = fmd3->FiducialHoles();
951   double           fiducialRadius = fmd3->GetFiducialRadius();
952   TGeoTube*        fiducialShape  = new TGeoTube("FMD3_fiducial_hole", 0, 
953                                                  fiducialRadius, 
954                                                  flangeDepth+.1);
955   Int_t            nFiducialHoles = fiducialHoles.GetEntriesFast();
956   double           flangeAngle    = TMath::Pi() / 4;
957   double           flangeX        = r5->Y()+flangeLength;
958   TVector2         flangeC(flangeX * TMath::Cos(flangeAngle), 
959                            flangeX * TMath::Sin(flangeAngle));
960   TString          flangeComb("FMD3_flange_base-(");
961 #if 0// For debugging geometry 
962   TGeoVolume* fiducialVolume = new TGeoVolume("FMD3_fiducial", fiducialShape);
963   fiducialVolume->SetLineColor(kGreen);
964 #else
965   (void*)fiducialShape;
966 #endif
967   for (Int_t i = 0; i < nFiducialHoles; i++) { 
968     TVector2&        v  =  *(static_cast<TVector2*>(fiducialHoles.At(i)));
969     v                   -= flangeC;
970     TVector2         r  =  v.Rotate(-flangeAngle);
971     TGeoTranslation* t1 =  new TGeoTranslation(r.X(),  r.Y(), 0);
972     TGeoTranslation* t2 =  new TGeoTranslation(r.X(), -r.Y(), 0);
973     t1->SetName(Form("FMD3_fiducial_hole_rot%d", 2*i+0));
974     t2->SetName(Form("FMD3_fiducial_hole_rot%d", 2*i+1));
975     t1->RegisterYourself();
976     t2->RegisterYourself();
977     flangeComb.Append(Form("FMD3_fiducial_hole:FMD3_fiducial_hole_rot%d+"
978                            "FMD3_fiducial_hole:FMD3_fiducial_hole_rot%d%c",
979                            2*i+0, 2*i+1, (i == nFiducialHoles-1 ? ')' : '+')));
980 #if 1 // For debugging geometry 
981     // support->AddNode(fiducialVolume, 2*i+0, t1);
982     // support->AddNode(fiducialVolume, 2*i+1, t2);
983 #endif
984   }
985   
986   // Final flange shape, and at to full shape 
987   TGeoCompositeShape* flangeShape = new TGeoCompositeShape(flangeComb.Data());
988   flangeShape->SetName("FMD3_flange");
989   for (Int_t i = 0; i < 2; i++) { 
990     TGeoRotation* rot = new TGeoRotation();
991     rot->RotateZ((i+.5)*90);
992     TVector2 v(flangeX, 0);
993     TVector2 w = v.Rotate((i+.5) * 2 * flangeAngle);
994     TGeoCombiTrans* trans = new TGeoCombiTrans(w.X(),w.Y(),
995                                                r4->X()+flangeDepth, rot);
996     trans->SetName(Form("FMD3_flange_matrix%d", i));
997     trans->RegisterYourself();
998     coneComb.Append(Form("+FMD3_flange:FMD3_flange_matrix%d", i));
999   }
1000   coneComb.Append(")-(");
1001   
1002   //__________________________________________________________________
1003   // Holes 
1004   Double_t holeL  = (fmd3->GetHoleLength()-1)/2;
1005   Double_t holeD  = fmd3->GetHoleDepth()/2;
1006   Double_t holeLW = fmd3->GetHoleLowWidth()/2;
1007   Double_t holeHW = fmd3->GetHoleHighWidth()/2;
1008   Double_t holeA  = fmd3->GetConeOuterAngle() - 1 * TMath::Pi() / 180;
1009   Double_t holeZ  = (fmd3->GetHoleOffset() 
1010                      + holeL * TMath::Cos(holeA)
1011                      - holeD * TMath::Sin(holeA));
1012   Double_t holeX  = (fmd3->ConeR(-holeZ + fmd3->GetInnerZ() + fmd3->GetNoseZ()) 
1013                      - holeD * TMath::Cos(holeA));
1014   Double_t plateZ  = (fmd3->GetHoleOffset() 
1015                      + holeL * TMath::Cos(holeA)
1016                      - 0.033 * TMath::Sin(holeA));
1017   Double_t plateX = (fmd3->ConeR(-plateZ + fmd3->GetInnerZ()+fmd3->GetNoseZ()) 
1018                      - 0.033 * TMath::Cos(holeA));
1019   TGeoTrd1* holeShape = new TGeoTrd1("FMD3_cone_hole", 
1020                                      holeLW, holeHW, holeD, holeL);
1021   TGeoTrd1* plateShape = new TGeoTrd1("FMD3_cooling_plate", 
1022                                       holeLW, holeHW, .033, holeL);
1023   TGeoRotation* holeRot = new TGeoRotation();
1024   holeRot->SetName("FMD3_cone_hole_rotation");
1025   holeRot->RotateZ(90);
1026   holeRot->RotateY(holeA*180/TMath::Pi());
1027   TGeoCombiTrans* holeBaseTrans = new TGeoCombiTrans(holeX, 0, holeZ, holeRot);
1028   holeBaseTrans->SetName("FMD3_cone_hole_base_matrix");
1029   TGeoCombiTrans* plateBaseTrans = new TGeoCombiTrans(plateX, 0,plateZ,holeRot);
1030   (void*)holeShape;
1031   TGeoVolume* plateVolume = new TGeoVolume("FMD3_cooling_plate", 
1032                                            plateShape, fAl);
1033   plateShape->SetTitle("FMD3 cooling plate");
1034   plateVolume->SetTitle("FMD3 cooling plate");
1035   for (Int_t i = 0; i < 4; i++) { 
1036     Double_t        ang   = 360. / 8 * (i + .5);
1037     TGeoCombiTrans* trans = new TGeoCombiTrans(*holeBaseTrans);
1038     trans->RotateZ(ang);
1039     trans->SetName(Form("FMD3_cone_hole_matrix%d", i));
1040     trans->RegisterYourself();
1041     trans = new TGeoCombiTrans(*plateBaseTrans);
1042     trans->RotateZ(ang);
1043     trans->SetName(Form("FMD3_cooling_plate_matrix%d", i));
1044     coneComb.Append(Form("FMD3_cone_hole:FMD3_cone_hole_matrix%d+", i));
1045     support->AddNode(plateVolume, i, trans);
1046   }
1047   
1048   //__________________________________________________________________
1049   // Bolts
1050   Double_t boltRadius = fmd3->GetBoltRadius();
1051   Double_t boltLength = fmd3->GetBoltLength() / 2;
1052   Double_t boltZ1     = fmd3->GetInnerZ()+fmd3->GetNoseZ()-10;
1053   Double_t boltZ2     = fmd3->GetInnerZ()+fmd3->GetNoseZ()-20;
1054   Double_t boltXE     = 2*boltLength*TMath::Cos(fmd3->GetConeOuterAngle());
1055   Double_t boltX1     = (fmd3->ConeR(boltZ1) - boltXE);
1056   Double_t boltX2     = (fmd3->ConeR(boltZ2) - boltXE);
1057   
1058   new TGeoTube("FMD3_bolt_hole", 0, boltRadius, boltLength+.2);
1059   TGeoTube* boltShape = new TGeoTube("FMD3_bolt", 0, boltRadius, boltLength);
1060   TGeoRotation* boltRot = new TGeoRotation();
1061   boltRot->RotateY(-fmd3->GetConeOuterAngle()*180/TMath::Pi());
1062   TGeoCombiTrans* boltTrans1 = new TGeoCombiTrans(boltX1, 0, 10, boltRot);
1063   TGeoCombiTrans* boltTrans2 = new TGeoCombiTrans(boltX2, 0, 20, boltRot);
1064   TGeoCombiTrans* boltTrans3 = new TGeoCombiTrans(*boltTrans1);
1065   TGeoCombiTrans* boltTrans4 = new TGeoCombiTrans(*boltTrans2);
1066   boltTrans3->RotateZ(180);
1067   boltTrans4->RotateZ(180);
1068   boltTrans1->SetName("FMD3_bolt_matrix1");
1069   boltTrans2->SetName("FMD3_bolt_matrix2");
1070   boltTrans3->SetName("FMD3_bolt_matrix3");
1071   boltTrans4->SetName("FMD3_bolt_matrix4");
1072   boltTrans1->RegisterYourself();
1073   boltTrans2->RegisterYourself();
1074   boltTrans3->RegisterYourself();
1075   boltTrans4->RegisterYourself();
1076   coneComb.Append("FMD3_bolt_hole:FMD3_bolt_matrix1"
1077                   "+FMD3_bolt_hole:FMD3_bolt_matrix2"
1078                   "+FMD3_bolt_hole:FMD3_bolt_matrix3"
1079                   "+FMD3_bolt_hole:FMD3_bolt_matrix4)");
1080   TGeoVolume*     boltVolume = new TGeoVolume("FMD3_bolt", boltShape, fSteel);
1081   support->AddNode(boltVolume, 1, boltTrans1);
1082   support->AddNode(boltVolume, 2, boltTrans2);
1083   boltShape->SetTitle("FMD3 steering bolt");
1084   boltVolume->SetTitle("FMD3 steering bolt");
1085   
1086   //__________________________________________________________________
1087   // Final cone
1088   TGeoCompositeShape* coneShape = new TGeoCompositeShape(coneComb.Data());
1089   coneShape->SetName("FMD3_cone");
1090   coneShape->SetTitle("FMD3 cone");
1091   TGeoVolume*  coneVolume = new TGeoVolume("FMD3_Cone", coneShape, fC);
1092   coneVolume->SetLineColor(kRed);
1093   support->AddNode(coneVolume, 0, new TGeoTranslation(0, 0, 0));
1094
1095   //__________________________________________________________________
1096   // Tension boxes. 
1097   TGeoBBox* tensionOuter = new TGeoBBox("FMD3_tension_outer", .5, 3, 5);
1098   new TGeoBBox("FMD3_tension_inner", .51, 2.5, 4.6);
1099   TString tensionExpr("FMD3_tension_outer-FMD3_tension_inner");
1100   TGeoCompositeShape* tensionShape = new TGeoCompositeShape(tensionExpr.Data());
1101   tensionShape->SetName("FMD3_tension_box");
1102   tensionShape->SetTitle("FMD3 tension box");
1103   TGeoVolume*      tensionFrame = new TGeoVolume("FMD3_tension_frame",
1104                                                   tensionShape, fAl);
1105   TGeoTube*        springShape  = new TGeoTube("FMD3_tension_spring", 
1106                                                0, .3, 4.3/2);
1107   TGeoVolume*      springVolume = new TGeoVolume("FMD3_tension_spring", 
1108                                                  springShape, fSteel);
1109   TGeoVolume*      tensionBox   = new TGeoVolume("FMD3_tension_box", 
1110                                                  tensionOuter, fAir);
1111   tensionBox->AddNode(tensionFrame, 0);
1112   tensionBox->AddNode(springVolume, 0, new TGeoTranslation(0,0,4.2/2));
1113   
1114   Double_t         tensionD     = 5*TMath::Cos(fmd3->GetConeOuterAngle());
1115   Double_t         tensionZ     = (r4->Z() - 2 * tensionD - 5 -
1116                                    2*.5*TMath::Cos(fmd3->GetConeOuterAngle()));
1117   Double_t         tensionX     = (fmd3->ConeR(fmd3->GetInnerZ()
1118                                                +fmd3->GetNoseZ() 
1119                                                -tensionZ) + 
1120                                    2*.5*TMath::Cos(fmd3->GetConeOuterAngle())); 
1121   TGeoRotation*    tensionRot   = new TGeoRotation();
1122   tensionRot->RotateY(180/TMath::Pi()*fmd3->GetConeOuterAngle());
1123   TGeoCombiTrans*  tensionBase  = new TGeoCombiTrans(tensionX, 0, tensionZ, 
1124                                                      tensionRot);
1125   
1126   Double_t         wireT        = .1;
1127   Double_t         wireR1       = fmd3->ConeR(fmd3->GetInnerZ()
1128                                               +fmd3->GetNoseZ()) + wireT;
1129   Double_t         wireR2       = fmd3->ConeR(fmd3->GetInnerZ()
1130                                               +fmd3->GetNoseZ()-
1131                                               tensionZ+tensionD) + wireT;
1132   Double_t         wireL        = TMath::Sqrt(TMath::Power(wireR1-wireR2,2)+ 
1133                                               TMath::Power(tensionZ-
1134                                                            tensionD,2));
1135   Double_t         wireAngle    = TMath::ATan2(wireR2-wireR1,tensionZ-tensionD);
1136   TGeoTube*        wireShape    = new TGeoTube("FMD3_wire", 0, wireT, wireL/2);
1137   TGeoVolume*      wireVolume   = new TGeoVolume("FMD3_wire", wireShape,fSteel);
1138   TGeoRotation*    wireRot      = new TGeoRotation();
1139   wireRot->RotateY(180/TMath::Pi()*wireAngle);
1140   TGeoCombiTrans*  wireBase     = new TGeoCombiTrans((wireR2-wireR1)/2+wireR1
1141                                                      +.1*TMath::Cos(wireAngle),
1142                                                      0,(tensionZ-tensionD)/2,
1143                                                      wireRot);
1144   for (Int_t i = 0; i < 2; i++) { 
1145     Double_t        thisAngle = (i+.5) * 90;
1146     TGeoCombiTrans* thisTrans = new TGeoCombiTrans(*tensionBase);
1147     thisTrans->RotateZ(thisAngle);
1148     support->AddNode(tensionBox, i, thisTrans);
1149     thisTrans = new TGeoCombiTrans(*wireBase);
1150     thisTrans->RotateZ(thisAngle);
1151     support->AddNode(wireVolume, i, thisTrans);
1152   }
1153
1154   //__________________________________________________________________
1155   // Place support volumes in half-detector volumes 
1156   Double_t         z  = fmd3->GetInnerZ();
1157   TGeoTranslation* t1 = new TGeoTranslation(0, 0, -fmd3->GetNoseZ());
1158   fmd3TopVolume->AddNode(support, 1, t1);
1159   TGeoCombiTrans*  t2 = new TGeoCombiTrans(*t1);
1160   t2->RotateZ(180);
1161   fmd3BotVolume->AddNode(support, 2, t2);
1162
1163   TGeoRotation*   rot        = new TGeoRotation("FMD3 rotatation");
1164   rot->RotateY(180);
1165   TGeoVolume*     top        = gGeoManager->GetVolume("ALIC");
1166   TGeoMatrix* mmatrix        = new TGeoCombiTrans("FMD3 trans", 0, 0, z, rot);
1167   AliFMDDebug(5, ("Placing volumes %s and %s in ALIC at z=%f", 
1168                    fmd3TopVolume->GetName(), fmd3BotVolume->GetName(), z));
1169   top->AddNode(fmd3TopVolume, fmd3->GetId(), mmatrix);
1170   top->AddNode(fmd3BotVolume, fmd3->GetId(), mmatrix);
1171
1172   return 0;
1173 }
1174
1175 #else
1176 //____________________________________________________________________
1177 TGeoVolume*
1178 AliFMDGeometryBuilder::FMD3Geometry(AliFMD3* fmd3, 
1179                                     TGeoVolume* innerTop, 
1180                                     TGeoVolume* innerBot, 
1181                                     TGeoVolume* outerTop,
1182                                     TGeoVolume* outerBot) 
1183 {
1184   // Setup the FMD3 geometry.  The FMD2 has a rather elaborate support
1185   // structure, as the support will also support the vacuum
1186   // beam-pipe. 
1187   // 
1188   // See also AliFMDGeometryBuilder::DetectorGeometry 
1189   // 
1190   if (!fmd3 || !innerTop || !innerBot || !outerTop || !outerBot) return 0;
1191   Double_t nlen    = fmd3->GetNoseLength();
1192   Double_t nz      = fmd3->GetNoseZ();
1193   Double_t noser1  = fmd3->GetNoseLowR();
1194   Double_t noser2  = fmd3->GetNoseHighR();
1195   Double_t conet   = fmd3->GetBeamThickness();
1196   Double_t conel   = fmd3->GetConeLength();
1197   Double_t backl   = fmd3->GetBackLength();
1198   // Double_t backr1  = fmd3->GetBackLowR();
1199   Double_t backr2  = fmd3->GetBackHighR();
1200   Double_t zdist   = conel -  backl - nlen;
1201   Double_t tdist   = backr2 - noser2;
1202   // Double_t beaml   = TMath::Sqrt(zdist * zdist + tdist * tdist);
1203   Double_t theta   = -180. * TMath::ATan2(tdist, zdist) / TMath::Pi();
1204   Double_t flanger = fmd3->GetFlangeR();
1205   Double_t z       = fmd3->GetInnerZ(); // fmd3->GetZ();
1206
1207   TGeoVolume* fmd3TopVolume = new TGeoVolumeAssembly(Form(fgkFMDName, 
1208                                                           fmd3->GetId(), 'T'));
1209   TGeoVolume* fmd3BotVolume = new TGeoVolumeAssembly(Form(fgkFMDName, 
1210                                                           fmd3->GetId(), 'B'));
1211   fmd3TopVolume->SetTitle("FMD3 top half");
1212   fmd3BotVolume->SetTitle("FMD3 bottom half");
1213   
1214   
1215   DetectorGeometry(fmd3, fmd3TopVolume, fmd3BotVolume, z, 
1216                    innerTop, innerBot, outerTop, outerBot);
1217
1218   
1219   TGeoVolumeAssembly* support = new TGeoVolumeAssembly("F3SU");
1220   support->SetTitle("FMD3 support");
1221   
1222   // Cone shape 
1223   TGeoPcon*        coneBase = new TGeoPcon("FMD3 cone base", 0, 180, 6);
1224   const TObjArray& radii    = fmd3.ConeRadii();
1225   TVector3*        v1       = 0;
1226   TVector3*        v4       = 0;
1227   for (Int_t i = 0; i < radii.GetEntriesFast(); i++) { 
1228     TVector3* v = static_cast<TVector3*>(radii.At(i));
1229     coneBase->DefineSection(i,  v->X(), v->Y(), v->Z());
1230     if (i == 1) v1 = v;
1231     if (i == 4) v4 = v;
1232     
1233   }
1234   Double_t  holeL = TMath::Sqrt(TMath::Power(v4->Z()-v1->Z(),2) + 
1235                                 TMath::Power(v4->X()-v1->X(),2));
1236   
1237   TGeoTrd1*       coneHole  = new TGeoTrd1("F3SC_hole",2,8,conet*3,
1238                                            (conel-2-2)/2);
1239   
1240
1241
1242   // Nose volume 
1243   TGeoTubeSeg* noseShape  = new TGeoTubeSeg(noser1, noser2, nlen / 2, 0, 180);
1244   TGeoVolume*  noseVolume = new TGeoVolume(fgkNoseName, noseShape, fC);
1245   support->AddNode(noseVolume, 0, new TGeoTranslation(0, 0, nlen/2));
1246   noseShape->SetName(fgkNoseName);
1247   noseShape->SetTitle("FMD3 nose");
1248   noseVolume->SetTitle("FMD3 nose");
1249   
1250   // Steel bolts 
1251   TGeoTube*       boltShape  = new TGeoTube("F3SB", 0, 0.3, conet / 2);
1252   TGeoVolume*     boltVolume = new TGeoVolume("F3SB", boltShape, fSteel);
1253   Double_t        z1         = -10;
1254   Double_t        x1         = (fmd3->ConeR(nz+z1));
1255   TGeoRotation*   r1         = new TGeoRotation();
1256   r1->RotateY(theta);
1257   TGeoCombiTrans* t          = new TGeoCombiTrans("F3SB1",x1,0,-z1,r1);
1258   support->AddNode(boltVolume, 1, t);
1259   z1                         = -20;
1260   x1                         = (fmd3->ConeR(nz+z1));
1261   t                          = new TGeoCombiTrans("F3SB2",x1,0,-z1,r1);
1262   support->AddNode(boltVolume, 2, t);
1263   boltShape->SetTitle("FMD3 steering bolt");
1264   boltVolume->SetTitle("FMD3 steering bolt");
1265
1266   // Cooling plates
1267   TGeoTrd1*   plateShape  = new TGeoTrd1(2, 8, 0.1, (conel-2-2)/2-.1);
1268   TGeoVolume* plateVolume = new TGeoVolume("F3CO", plateShape, fAl);
1269   plateShape->SetName("F3C0");
1270   plateShape->SetTitle("FMD3 cooling plate");
1271   plateVolume->SetTitle("FMD3 cooling plate");
1272
1273   // Shape for carbon half-cone
1274   TGeoConeSeg*    innerCone = new TGeoConeSeg("F3SC_inner", conel/2,
1275                                               noser2-conet, noser2, 
1276                                               backr2-conet, backr2, 0., 180.);
1277   innerCone->SetTitle("FMD3 cone inner");
1278   TGeoTrd1*       coneHole  = new TGeoTrd1("F3SC_hole",2,8,conet*3,
1279                                            (conel-2-2)/2);
1280   coneHole->SetTitle("FMD3 cone hole");
1281   Double_t        holeAng   = TMath::ATan2(backr2 - noser2, conel);
1282   Double_t        holeX     = ((conel-2) / 2 * TMath::Sin(holeAng) +
1283                                conet     * TMath::Cos(holeAng) +
1284                                noser2);
1285   TGeoRotation*   holeRot   = new TGeoRotation();
1286   holeRot->SetName("FMD3 cone hole rotation");
1287   holeRot->RotateZ(90);
1288   holeRot->RotateY(holeAng*180./TMath::Pi());
1289   TGeoCombiTrans* holeTrans = new TGeoCombiTrans(holeX, 0, -2, holeRot);
1290   holeRot->SetName("FMD3 cone hole");
1291
1292   // Build-up the composite shape for the cone, and add cooling plates
1293   // at the same time. 
1294   TString coneExp("F3SC_inner-(");
1295   for (int i = 0; i < 4; i++) { 
1296     Double_t        thisAng   = 360. / 8 * (i + .5);
1297     TGeoCombiTrans* thisTrans = new TGeoCombiTrans(*holeTrans);
1298     thisTrans->RotateZ(thisAng);
1299     thisTrans->SetName(Form("F3SC_rot%d", i));
1300     thisTrans->RegisterYourself();
1301     coneExp.Append(Form("F3SC_hole:F3SC_rot%d+", i));
1302
1303     const Double_t* tt         = thisTrans->GetTranslation();
1304     Double_t        x          = tt[0]+1*TMath::Cos(thisAng*TMath::Pi()/180);
1305     Double_t        y          = tt[1]+1*TMath::Sin(thisAng*TMath::Pi()/180);
1306     TGeoCombiTrans* plateTrans = new TGeoCombiTrans(x,y,tt[2]-1+nlen+conel/2,
1307                                                     thisTrans->GetRotation());
1308     support->AddNode(plateVolume, i, plateTrans);
1309   }
1310   // Remove bolt holes 
1311   coneExp.Append("F3SB:F3SB1+F3SB:F3SB2)");
1312
1313   // Finalize the half-cone shape and add volume
1314   TGeoCompositeShape* coneShape  = new TGeoCompositeShape(coneExp.Data());
1315   TGeoVolume*         coneVolume = new TGeoVolume("F3SC", coneShape, fC);
1316   coneShape->SetName("F3SC");
1317   coneShape->SetTitle("FMD3 cone");
1318   coneVolume->SetTitle("FMD3 cone");
1319   support->AddNode(coneVolume,1,new TGeoTranslation(0,0,nlen+conel/2));
1320   
1321   // The flanges 
1322   TGeoBBox* flangeShape    = new TGeoBBox((flanger - backr2) / 2, 
1323                                           fmd3->GetBeamWidth() / 2,
1324                                           backl / 2);
1325   TGeoVolume* flangeVolume = new TGeoVolume(Form(fgkFlangeName, fmd3->GetId()),
1326                                             flangeShape, fC);
1327   flangeShape->SetName(Form(fgkFlangeName, fmd3->GetId()));
1328   flangeShape->SetTitle("FMD3 flange");
1329   flangeVolume->SetTitle("FMD3 flange");
1330   
1331   Int_t    n               = fmd3->GetNFlange();
1332   Double_t r               = backr2 + (flanger - backr2) / 2;
1333   for (Int_t i = 0; i  < n/2; i++) {
1334     Double_t phi       = 360. / n * i + 180. / n;
1335     Double_t x         = r * TMath::Cos(TMath::Pi() / 180 * phi);
1336     Double_t y         = r * TMath::Sin(TMath::Pi() / 180 * phi);
1337     TGeoRotation* rot  = new TGeoRotation;
1338     rot->RotateZ(phi);
1339     TGeoMatrix* matrix = new TGeoCombiTrans(x, y, nlen+conel-backl/2, rot);
1340     matrix->SetName(Form("FMD3_flange_%02d", i));
1341     matrix->SetTitle(Form("FMD3_flange_%2d", i));
1342     support->AddNode(flangeVolume, i, matrix);
1343   }
1344
1345   // Place support volumes in half-detector volumes 
1346   z                          = fmd3->GetInnerZ();
1347   z1                         = z-nz;
1348   fmd3TopVolume->AddNode(support, 1, new TGeoTranslation(0,0,z1));
1349   r1                         = new TGeoRotation();
1350   r1->RotateZ(180);
1351   t                          = new TGeoCombiTrans(0,0,z1,r1);
1352   fmd3BotVolume->AddNode(support, 2, t);
1353
1354   TGeoRotation*   rot        = new TGeoRotation("FMD3 rotatation");
1355   rot->RotateY(180);
1356   TGeoVolume*     top        = gGeoManager->GetVolume("ALIC");
1357   TGeoMatrix* mmatrix        = new TGeoCombiTrans("FMD3 trans", 0, 0, z, rot);
1358   AliFMDDebug(5, ("Placing volumes %s and %s in ALIC at z=%f", 
1359                    fmd3TopVolume->GetName(), fmd3BotVolume->GetName(), z));
1360   top->AddNode(fmd3TopVolume, fmd3->GetId(), mmatrix);
1361   top->AddNode(fmd3BotVolume, fmd3->GetId(), mmatrix);
1362
1363   return 0;
1364 }
1365 #endif
1366
1367 //____________________________________________________________________
1368 void
1369 AliFMDGeometryBuilder::Exec(Option_t*) 
1370 {
1371   // Setup up the FMD geometry. 
1372   AliFMDDebug(1, ("\tGeometry options: %s",
1373                     (fDetailed  ? "divided into strips" : "one volume")));
1374   if (!gGeoManager) {
1375     AliFatal("No TGeoManager defined");
1376     return;
1377   }
1378
1379   fSi      = gGeoManager->GetMedium("FMD_Si$");
1380   fC       = gGeoManager->GetMedium("FMD_Carbon$");
1381   fAl      = gGeoManager->GetMedium("FMD_Aluminum$");
1382   fChip    = gGeoManager->GetMedium("FMD_Si Chip$");
1383   fAir     = gGeoManager->GetMedium("FMD_Air$");
1384   fPCB     = gGeoManager->GetMedium("FMD_PCB$");
1385   fPlastic = gGeoManager->GetMedium("FMD_Plastic$");
1386   fCopper  = gGeoManager->GetMedium("FMD_Copper$");
1387   fSteel   = gGeoManager->GetMedium("FMD_Steel$");
1388
1389   if (!fSi||!fC||!fAl||!fChip||!fAir||!fPCB||!fPlastic||!fCopper||!fSteel) {
1390     AliError("Failed to get some or all tracking mediums");
1391     return;
1392   }    
1393   AliFMDGeometry* fmd = AliFMDGeometry::Instance();
1394   AliFMDRing* inner = fmd->GetInner();
1395   AliFMDRing* outer = fmd->GetOuter();
1396   RingGeometry(inner);
1397   RingGeometry(outer);
1398   TGeoVolume* innerTop = gGeoManager->GetVolume(Form(fgkRingTopName, 
1399                                                      inner->GetId()));
1400   TGeoVolume* innerBot = gGeoManager->GetVolume(Form(fgkRingBotName, 
1401                                                      inner->GetId()));
1402   TGeoVolume* outerTop = gGeoManager->GetVolume(Form(fgkRingTopName, 
1403                                                      outer->GetId()));
1404   TGeoVolume* outerBot = gGeoManager->GetVolume(Form(fgkRingBotName, 
1405                                                      outer->GetId()));
1406   
1407   FMD1Geometry(fmd->GetFMD1(), innerTop, innerBot);
1408   FMD2Geometry(fmd->GetFMD2(), innerTop, innerBot, outerTop, outerBot);
1409   FMD3Geometry(fmd->GetFMD3(), innerTop, innerBot, outerTop, outerBot);
1410 #ifndef USE_PRE_MOVE
1411   fmd->SetSectorOff(fSectorOff);
1412   fmd->SetModuleOff(fModuleOff);
1413   fmd->SetRingOff(fRingOff);
1414   fmd->SetDetectorOff(fDetectorOff);
1415   fmd->SetActive(fActiveId.fArray, fActiveId.fN);
1416 #endif
1417   // fmd->ExtractGeomInfo();
1418   
1419 }
1420
1421
1422 //____________________________________________________________________
1423 //
1424 // EOF
1425 //