00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include "Riostream.h"
00014
00015 #include "TGeoManager.h"
00016 #include "TGeoVoxelFinder.h"
00017 #include "TGeoMatrix.h"
00018 #include "TGeoVolume.h"
00019 #include "TGeoNode.h"
00020 #include "TGeoShapeAssembly.h"
00021 #include "TBuffer3D.h"
00022 #include "TBuffer3DTypes.h"
00023 #include "TMath.h"
00024
00025
00026
00027
00028
00029
00030
00031 ClassImp(TGeoShapeAssembly)
00032
00033
00034 TGeoShapeAssembly::TGeoShapeAssembly()
00035 {
00036
00037 fCurrent = 0;
00038 fNext = 0;
00039 fVolume = 0;
00040 fBBoxOK = kFALSE;
00041 }
00042
00043
00044
00045 TGeoShapeAssembly::TGeoShapeAssembly(TGeoVolumeAssembly *vol)
00046 {
00047
00048 fVolume = vol;
00049 fCurrent = 0;
00050 fNext = 0;
00051 fBBoxOK = kFALSE;
00052 }
00053
00054
00055
00056 TGeoShapeAssembly::~TGeoShapeAssembly()
00057 {
00058
00059 }
00060
00061
00062 void TGeoShapeAssembly::ComputeBBox()
00063 {
00064
00065 if (!fVolume) {
00066 Fatal("ComputeBBox", "Assembly shape %s without volume", GetName());
00067 return;
00068 }
00069
00070 if (fBBoxOK) return;
00071 Int_t nd = fVolume->GetNdaughters();
00072 if (!nd) {fBBoxOK = kTRUE; return;}
00073 TGeoNode *node;
00074 TGeoBBox *box;
00075 Double_t xmin, xmax, ymin, ymax, zmin, zmax;
00076 xmin = ymin = zmin = TGeoShape::Big();
00077 xmax = ymax = zmax = -TGeoShape::Big();
00078 Double_t vert[24];
00079 Double_t pt[3];
00080 for (Int_t i=0; i<nd; i++) {
00081 node = fVolume->GetNode(i);
00082
00083 if (node->GetVolume()->IsAssembly()) node->GetVolume()->GetShape()->ComputeBBox();
00084 box = (TGeoBBox*)node->GetVolume()->GetShape();
00085 box->SetBoxPoints(vert);
00086 for (Int_t ipt=0; ipt<8; ipt++) {
00087 node->LocalToMaster(&vert[3*ipt], pt);
00088 if (pt[0]<xmin) xmin=pt[0];
00089 if (pt[0]>xmax) xmax=pt[0];
00090 if (pt[1]<ymin) ymin=pt[1];
00091 if (pt[1]>ymax) ymax=pt[1];
00092 if (pt[2]<zmin) zmin=pt[2];
00093 if (pt[2]>zmax) zmax=pt[2];
00094 }
00095 }
00096 fDX = 0.5*(xmax-xmin);
00097 fOrigin[0] = 0.5*(xmin+xmax);
00098 fDY = 0.5*(ymax-ymin);
00099 fOrigin[1] = 0.5*(ymin+ymax);
00100 fDZ = 0.5*(zmax-zmin);
00101 fOrigin[2] = 0.5*(zmin+zmax);
00102 fBBoxOK = kTRUE;
00103 }
00104
00105
00106 void TGeoShapeAssembly::RecomputeBoxLast()
00107 {
00108
00109 Int_t nd = fVolume->GetNdaughters();
00110 if (!nd) {
00111 Warning("RecomputeBoxLast", "No daughters for volume %s yet", fVolume->GetName());
00112 return;
00113 }
00114 TGeoNode *node = fVolume->GetNode(nd-1);
00115 Double_t xmin, xmax, ymin, ymax, zmin, zmax;
00116 if (nd==1) {
00117 xmin = ymin = zmin = TGeoShape::Big();
00118 xmax = ymax = zmax = -TGeoShape::Big();
00119 } else {
00120 xmin = fOrigin[0]-fDX;
00121 xmax = fOrigin[0]+fDX;
00122 ymin = fOrigin[1]-fDY;
00123 ymax = fOrigin[1]+fDY;
00124 zmin = fOrigin[2]-fDZ;
00125 zmax = fOrigin[2]+fDZ;
00126 }
00127 Double_t vert[24];
00128 Double_t pt[3];
00129 TGeoBBox *box = (TGeoBBox*)node->GetVolume()->GetShape();
00130 if (TGeoShape::IsSameWithinTolerance(box->GetDX(), 0) ||
00131 node->GetVolume()->IsAssembly()) node->GetVolume()->GetShape()->ComputeBBox();
00132 box->SetBoxPoints(vert);
00133 for (Int_t ipt=0; ipt<8; ipt++) {
00134 node->LocalToMaster(&vert[3*ipt], pt);
00135 if (pt[0]<xmin) xmin=pt[0];
00136 if (pt[0]>xmax) xmax=pt[0];
00137 if (pt[1]<ymin) ymin=pt[1];
00138 if (pt[1]>ymax) ymax=pt[1];
00139 if (pt[2]<zmin) zmin=pt[2];
00140 if (pt[2]>zmax) zmax=pt[2];
00141 }
00142 fDX = 0.5*(xmax-xmin);
00143 fOrigin[0] = 0.5*(xmin+xmax);
00144 fDY = 0.5*(ymax-ymin);
00145 fOrigin[1] = 0.5*(ymin+ymax);
00146 fDZ = 0.5*(zmax-zmin);
00147 fOrigin[2] = 0.5*(zmin+zmax);
00148 fBBoxOK = kTRUE;
00149 }
00150
00151
00152 void TGeoShapeAssembly::ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm)
00153 {
00154
00155 if (!fBBoxOK) ((TGeoShapeAssembly*)this)->ComputeBBox();
00156 Int_t inext = fVolume->GetNextNodeIndex();
00157 if (inext<0) {
00158 DistFromOutside(point,dir,3);
00159 inext = fVolume->GetNextNodeIndex();
00160 if (inext<0) {
00161 Error("ComputeNormal","Invalid inext=%i (Ncomponents=%i)",inext,fVolume->GetNdaughters());
00162 return;
00163 }
00164 }
00165 TGeoNode *node = fVolume->GetNode(inext);
00166 Double_t local[3],ldir[3],lnorm[3];
00167 node->MasterToLocal(point,local);
00168 node->MasterToLocalVect(dir,ldir);
00169 node->GetVolume()->GetShape()->ComputeNormal(local,ldir,lnorm);
00170 node->LocalToMasterVect(lnorm,norm);
00171 }
00172
00173
00174 Bool_t TGeoShapeAssembly::Contains(Double_t *point) const
00175 {
00176
00177 if (!fBBoxOK) ((TGeoShapeAssembly*)this)->ComputeBBox();
00178 if (!TGeoBBox::Contains(point)) return kFALSE;
00179 TGeoVoxelFinder *voxels = fVolume->GetVoxels();
00180 TGeoNode *node;
00181 TGeoShape *shape;
00182 Int_t *check_list = 0;
00183 Int_t ncheck, id;
00184 Double_t local[3];
00185 if (voxels) {
00186
00187 check_list = voxels->GetCheckList(&point[0], ncheck);
00188 if (!check_list) return kFALSE;
00189 for (id=0; id<ncheck; id++) {
00190 node = fVolume->GetNode(check_list[id]);
00191 shape = node->GetVolume()->GetShape();
00192 node->MasterToLocal(point,local);
00193 if (shape->Contains(local)) {
00194 fVolume->SetCurrentNodeIndex(check_list[id]);
00195 fVolume->SetNextNodeIndex(check_list[id]);
00196 return kTRUE;
00197 }
00198 }
00199 return kFALSE;
00200 }
00201 Int_t nd = fVolume->GetNdaughters();
00202 for (id=0; id<nd; id++) {
00203 node = fVolume->GetNode(id);
00204 shape = node->GetVolume()->GetShape();
00205 node->MasterToLocal(point,local);
00206 if (shape->Contains(local)) {
00207 fVolume->SetCurrentNodeIndex(id);
00208 fVolume->SetNextNodeIndex(id);
00209 return kTRUE;
00210 }
00211 }
00212 return kFALSE;
00213 }
00214
00215
00216 Int_t TGeoShapeAssembly::DistancetoPrimitive(Int_t , Int_t )
00217 {
00218
00219 return 9999;
00220 }
00221
00222
00223 Double_t TGeoShapeAssembly::DistFromInside(Double_t * , Double_t * , Int_t , Double_t , Double_t * ) const
00224 {
00225
00226 Info("DistFromInside", "Cannot compute distance from inside the assembly (but from a component)");
00227 return TGeoShape::Big();
00228 }
00229
00230
00231
00232 Double_t TGeoShapeAssembly::DistFromOutside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
00233 {
00234
00235
00236 if (!fBBoxOK) ((TGeoShapeAssembly*)this)->ComputeBBox();
00237 if (iact<3 && safe) {
00238 *safe = Safety(point, kFALSE);
00239 if (iact==0) return TGeoShape::Big();
00240 if ((iact==1) && (step<=*safe)) return TGeoShape::Big();
00241 }
00242
00243 Double_t snext = 0.0;
00244 Double_t dist;
00245 Double_t stepmax = step;
00246 Double_t pt[3];
00247 Int_t i;
00248 Bool_t found = kFALSE;
00249 memcpy(pt,point,3*sizeof(Double_t));
00250 if (!TGeoBBox::Contains(point)) {
00251 snext = TGeoBBox::DistFromOutside(point, dir, 3, stepmax);
00252 if (snext > stepmax) return TGeoShape::Big();
00253 for (i=0; i<3; i++) pt[i] += (snext+TGeoShape::Tolerance())*dir[i];
00254 if (Contains(pt)) {
00255 fVolume->SetNextNodeIndex(fVolume->GetCurrentNodeIndex());
00256 return snext;
00257 }
00258 snext += TGeoShape::Tolerance();
00259 stepmax -= snext;
00260 }
00261
00262 Int_t nd = fVolume->GetNdaughters();
00263 TGeoNode *node;
00264 Double_t lpoint[3],ldir[3];
00265 TGeoVoxelFinder *voxels = fVolume->GetVoxels();
00266 if (nd<5 || !voxels) {
00267 for (i=0; i<nd; i++) {
00268 node = fVolume->GetNode(i);
00269 if (voxels && voxels->IsSafeVoxel(pt, i, stepmax)) continue;
00270 node->MasterToLocal(pt, lpoint);
00271 node->MasterToLocalVect(dir, ldir);
00272 dist = node->GetVolume()->GetShape()->DistFromOutside(lpoint, ldir, 3, stepmax);
00273 if (dist<stepmax) {
00274 stepmax = dist;
00275 fVolume->SetNextNodeIndex(i);
00276 found = kTRUE;
00277 }
00278 }
00279 if (found) {
00280 snext += stepmax;
00281 return snext;
00282 }
00283 return TGeoShape::Big();
00284 }
00285
00286 Int_t ncheck = 0;
00287 Int_t *vlist = 0;
00288 voxels->SortCrossedVoxels(pt, dir);
00289 while ((vlist=voxels->GetNextVoxel(pt, dir, ncheck))) {
00290 for (i=0; i<ncheck; i++) {
00291 node = fVolume->GetNode(vlist[i]);
00292 node->MasterToLocal(pt, lpoint);
00293 node->MasterToLocalVect(dir, ldir);
00294 dist = node->GetVolume()->GetShape()->DistFromOutside(lpoint, ldir, 3, stepmax);
00295 if (dist<stepmax) {
00296 stepmax = dist;
00297 fVolume->SetNextNodeIndex(vlist[i]);
00298 found = kTRUE;
00299 }
00300 }
00301 }
00302 if (found) {
00303 snext += stepmax;
00304 return snext;
00305 }
00306 return TGeoShape::Big();
00307 }
00308
00309
00310 TGeoVolume *TGeoShapeAssembly::Divide(TGeoVolume * , const char *divname, Int_t , Int_t ,
00311 Double_t , Double_t )
00312 {
00313
00314 Error("Divide", "Assemblies cannot be divided. Division volume %s not created", divname);
00315 return 0;
00316 }
00317
00318
00319 TGeoShape *TGeoShapeAssembly::GetMakeRuntimeShape(TGeoShape * , TGeoMatrix * ) const
00320 {
00321
00322
00323 Error("GetMakeRuntimeShape", "Assemblies cannot be parametrized.");
00324 return NULL;
00325 }
00326
00327
00328 void TGeoShapeAssembly::InspectShape() const
00329 {
00330
00331 printf("*** Shape %s: TGeoShapeAssembly ***\n", GetName());
00332 printf(" Volume assembly %s with %i nodes\n", fVolume->GetName(), fVolume->GetNdaughters());
00333 printf(" Bounding box:\n");
00334 if (!fBBoxOK) ((TGeoShapeAssembly*)this)->ComputeBBox();
00335 TGeoBBox::InspectShape();
00336 }
00337
00338
00339 void TGeoShapeAssembly::SetSegsAndPols(TBuffer3D & ) const
00340 {
00341
00342 Error("SetSegsAndPols", "Drawing functions should not be called for assemblies, but rather for their content");
00343 }
00344
00345
00346 Double_t TGeoShapeAssembly::Safety(Double_t *point, Bool_t in) const
00347 {
00348
00349
00350 Double_t safety = TGeoShape::Big();
00351 Double_t pt[3], loc[3];
00352 if (!fBBoxOK) ((TGeoShapeAssembly*)this)->ComputeBBox();
00353 if (in) {
00354 Int_t index = fVolume->GetCurrentNodeIndex();
00355 TGeoVolume *vol = fVolume;
00356 TGeoNode *node;
00357 memcpy(loc, point, 3*sizeof(Double_t));
00358 while (index>=0) {
00359 memcpy(pt, loc, 3*sizeof(Double_t));
00360 node = vol->GetNode(index);
00361 node->GetMatrix()->MasterToLocal(pt,loc);
00362 vol = node->GetVolume();
00363 index = vol->GetCurrentNodeIndex();
00364 if (index<0) {
00365 safety = vol->GetShape()->Safety(loc, in);
00366 return safety;
00367 }
00368 }
00369 return TGeoShape::Big();
00370 }
00371 Double_t safe;
00372 TGeoVoxelFinder *voxels = fVolume->GetVoxels();
00373 Int_t nd = fVolume->GetNdaughters();
00374 Double_t *boxes = 0;
00375 if (voxels) boxes = voxels->GetBoxes();
00376 TGeoNode *node;
00377 for (Int_t id=0; id<nd; id++) {
00378 if (boxes && id>0) {
00379 Int_t ist = 6*id;
00380 Double_t dxyz = 0.;
00381 Double_t dxyz0 = TMath::Abs(point[0]-boxes[ist+3])-boxes[ist];
00382 if (dxyz0 > safety) continue;
00383 Double_t dxyz1 = TMath::Abs(point[1]-boxes[ist+4])-boxes[ist+1];
00384 if (dxyz1 > safety) continue;
00385 Double_t dxyz2 = TMath::Abs(point[2]-boxes[ist+5])-boxes[ist+2];
00386 if (dxyz2 > safety) continue;
00387 if (dxyz0>0) dxyz+=dxyz0*dxyz0;
00388 if (dxyz1>0) dxyz+=dxyz1*dxyz1;
00389 if (dxyz2>0) dxyz+=dxyz2*dxyz2;
00390 if (dxyz >= safety*safety) continue;
00391 }
00392 node = fVolume->GetNode(id);
00393 safe = node->Safety(point, kFALSE);
00394 if (safe<=0.0) return 0.0;
00395 if (safe<safety) safety = safe;
00396 }
00397 return safety;
00398 }
00399
00400
00401 void TGeoShapeAssembly::SavePrimitive(ostream & , Option_t * )
00402 {
00403
00404 }
00405
00406
00407 void TGeoShapeAssembly::SetPoints(Double_t * ) const
00408 {
00409
00410 Error("SetPoints", "Drawing functions should not be called for assemblies, but rather for their content");
00411 }
00412
00413
00414 void TGeoShapeAssembly::SetPoints(Float_t * ) const
00415 {
00416
00417 Error("SetPoints", "Drawing functions should not be called for assemblies, but rather for their content");
00418 }
00419
00420
00421 void TGeoShapeAssembly::GetMeshNumbers(Int_t &nvert, Int_t &nsegs, Int_t &npols) const
00422 {
00423
00424 nvert = 0;
00425 nsegs = 0;
00426 npols = 0;
00427 }
00428