Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
TGeoShapeAssembly.cxx
Go to the documentation of this file.
1 // @(#)root/geom:$Id$
2 // Author: Andrei Gheata 02/06/05
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 
13 #include "Riostream.h"
14 
15 #include "TGeoManager.h"
16 #include "TGeoVoxelFinder.h"
17 #include "TGeoMatrix.h"
18 #include "TGeoVolume.h"
19 #include "TGeoNode.h"
20 #include "TGeoShapeAssembly.h"
21 #include "TBuffer3D.h"
22 #include "TBuffer3DTypes.h"
23 #include "TMath.h"
24 
25 /** \class TGeoShapeAssembly
26 \ingroup Geometry_classes
27 
28 The shape encapsulating an assembly (union) of volumes.
29 Automatically created by TGeoVolumeAssembly class
30 */
31 
32 ClassImp(TGeoShapeAssembly);
33 
34 ////////////////////////////////////////////////////////////////////////////////
35 /// Default constructor
36 
37 TGeoShapeAssembly::TGeoShapeAssembly()
38 {
39  fVolume = 0;
40  fBBoxOK = kFALSE;
41 }
42 
43 
44 ////////////////////////////////////////////////////////////////////////////////
45 /// Constructor specifying hyperboloid parameters.
46 
47 TGeoShapeAssembly::TGeoShapeAssembly(TGeoVolumeAssembly *vol)
48 {
49  fVolume = vol;
50  fBBoxOK = kFALSE;
51 }
52 
53 
54 ////////////////////////////////////////////////////////////////////////////////
55 /// destructor
56 
57 TGeoShapeAssembly::~TGeoShapeAssembly()
58 {
59 }
60 
61 ////////////////////////////////////////////////////////////////////////////////
62 /// Compute bounding box of the assembly
63 
64 void TGeoShapeAssembly::ComputeBBox()
65 {
66  if (!fVolume) {
67  Fatal("ComputeBBox", "Assembly shape %s without volume", GetName());
68  return;
69  }
70  // Make sure bbox is computed only once or recomputed only if invalidated (by alignment)
71  if (fBBoxOK) return;
72  Int_t nd = fVolume->GetNdaughters();
73  if (!nd) {fBBoxOK = kTRUE; return;}
74  TGeoNode *node;
75  TGeoBBox *box;
76  Double_t xmin, xmax, ymin, ymax, zmin, zmax;
77  xmin = ymin = zmin = TGeoShape::Big();
78  xmax = ymax = zmax = -TGeoShape::Big();
79  Double_t vert[24];
80  Double_t pt[3];
81  for (Int_t i=0; i<nd; i++) {
82  node = fVolume->GetNode(i);
83  // Make sure that all assembly daughters have computed their bboxes
84  if (node->GetVolume()->IsAssembly()) node->GetVolume()->GetShape()->ComputeBBox();
85  box = (TGeoBBox*)node->GetVolume()->GetShape();
86  box->SetBoxPoints(vert);
87  for (Int_t ipt=0; ipt<8; ipt++) {
88  node->LocalToMaster(&vert[3*ipt], pt);
89  if (pt[0]<xmin) xmin=pt[0];
90  if (pt[0]>xmax) xmax=pt[0];
91  if (pt[1]<ymin) ymin=pt[1];
92  if (pt[1]>ymax) ymax=pt[1];
93  if (pt[2]<zmin) zmin=pt[2];
94  if (pt[2]>zmax) zmax=pt[2];
95  }
96  }
97  fDX = 0.5*(xmax-xmin);
98  fOrigin[0] = 0.5*(xmin+xmax);
99  fDY = 0.5*(ymax-ymin);
100  fOrigin[1] = 0.5*(ymin+ymax);
101  fDZ = 0.5*(zmax-zmin);
102  fOrigin[2] = 0.5*(zmin+zmax);
103  if (fDX>0 && fDY>0 && fDZ>0) fBBoxOK = kTRUE;
104 }
105 
106 ////////////////////////////////////////////////////////////////////////////////
107 /// Recompute bounding box of the assembly after adding a node.
108 
109 void TGeoShapeAssembly::RecomputeBoxLast()
110 {
111  Int_t nd = fVolume->GetNdaughters();
112  if (!nd) {
113  Warning("RecomputeBoxLast", "No daughters for volume %s yet", fVolume->GetName());
114  return;
115  }
116  TGeoNode *node = fVolume->GetNode(nd-1);
117  Double_t xmin, xmax, ymin, ymax, zmin, zmax;
118  if (nd==1) {
119  xmin = ymin = zmin = TGeoShape::Big();
120  xmax = ymax = zmax = -TGeoShape::Big();
121  } else {
122  xmin = fOrigin[0]-fDX;
123  xmax = fOrigin[0]+fDX;
124  ymin = fOrigin[1]-fDY;
125  ymax = fOrigin[1]+fDY;
126  zmin = fOrigin[2]-fDZ;
127  zmax = fOrigin[2]+fDZ;
128  }
129  Double_t vert[24];
130  Double_t pt[3];
131  TGeoBBox *box = (TGeoBBox*)node->GetVolume()->GetShape();
132  if (TGeoShape::IsSameWithinTolerance(box->GetDX(), 0) ||
133  node->GetVolume()->IsAssembly()) node->GetVolume()->GetShape()->ComputeBBox();
134  box->SetBoxPoints(vert);
135  for (Int_t ipt=0; ipt<8; ipt++) {
136  node->LocalToMaster(&vert[3*ipt], pt);
137  if (pt[0]<xmin) xmin=pt[0];
138  if (pt[0]>xmax) xmax=pt[0];
139  if (pt[1]<ymin) ymin=pt[1];
140  if (pt[1]>ymax) ymax=pt[1];
141  if (pt[2]<zmin) zmin=pt[2];
142  if (pt[2]>zmax) zmax=pt[2];
143  }
144  fDX = 0.5*(xmax-xmin);
145  fOrigin[0] = 0.5*(xmin+xmax);
146  fDY = 0.5*(ymax-ymin);
147  fOrigin[1] = 0.5*(ymin+ymax);
148  fDZ = 0.5*(zmax-zmin);
149  fOrigin[2] = 0.5*(zmin+zmax);
150  fBBoxOK = kTRUE;
151 }
152 
153 ////////////////////////////////////////////////////////////////////////////////
154 /// Compute normal to closest surface from POINT. Should not be called.
155 
156 void TGeoShapeAssembly::ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm)
157 {
158  if (!fBBoxOK) ((TGeoShapeAssembly*)this)->ComputeBBox();
159  Int_t inext = fVolume->GetNextNodeIndex();
160  if (inext<0) {
161  DistFromOutside(point,dir,3);
162  inext = fVolume->GetNextNodeIndex();
163  if (inext<0) {
164  Error("ComputeNormal","Invalid inext=%i (Ncomponents=%i)",inext,fVolume->GetNdaughters());
165  return;
166  }
167  }
168  TGeoNode *node = fVolume->GetNode(inext);
169  Double_t local[3],ldir[3],lnorm[3];
170  node->MasterToLocal(point,local);
171  node->MasterToLocalVect(dir,ldir);
172  node->GetVolume()->GetShape()->ComputeNormal(local,ldir,lnorm);
173  node->LocalToMasterVect(lnorm,norm);
174 }
175 
176 ////////////////////////////////////////////////////////////////////////////////
177 /// Test if point is inside the assembly
178 
179 Bool_t TGeoShapeAssembly::Contains(const Double_t *point) const
180 {
181  if (!fBBoxOK) ((TGeoShapeAssembly*)this)->ComputeBBox();
182  if (!TGeoBBox::Contains(point)) return kFALSE;
183  TGeoVoxelFinder *voxels = fVolume->GetVoxels();
184  TGeoNode *node;
185  TGeoShape *shape;
186  Int_t *check_list = 0;
187  Int_t ncheck, id;
188  Double_t local[3];
189  if (voxels) {
190  // get the list of nodes passing thorough the current voxel
191  TGeoNavigator *nav = gGeoManager->GetCurrentNavigator();
192  TGeoStateInfo &td = *nav->GetCache()->GetInfo();
193  check_list = voxels->GetCheckList(point, ncheck, td);
194  if (!check_list) {
195  nav->GetCache()->ReleaseInfo();
196  return kFALSE;
197  }
198  for (id=0; id<ncheck; id++) {
199  node = fVolume->GetNode(check_list[id]);
200  shape = node->GetVolume()->GetShape();
201  node->MasterToLocal(point,local);
202  if (shape->Contains(local)) {
203  fVolume->SetCurrentNodeIndex(check_list[id]);
204  fVolume->SetNextNodeIndex(check_list[id]);
205  nav->GetCache()->ReleaseInfo();
206  return kTRUE;
207  }
208  }
209  nav->GetCache()->ReleaseInfo();
210  return kFALSE;
211  }
212  Int_t nd = fVolume->GetNdaughters();
213  for (id=0; id<nd; id++) {
214  node = fVolume->GetNode(id);
215  shape = node->GetVolume()->GetShape();
216  node->MasterToLocal(point,local);
217  if (shape->Contains(local)) {
218  fVolume->SetCurrentNodeIndex(id);
219  fVolume->SetNextNodeIndex(id);
220  return kTRUE;
221  }
222  }
223  return kFALSE;
224 }
225 
226 ////////////////////////////////////////////////////////////////////////////////
227 /// compute closest distance from point px,py to each vertex. Should not be called.
228 
229 Int_t TGeoShapeAssembly::DistancetoPrimitive(Int_t /*px*/, Int_t /*py*/)
230 {
231  return 9999;
232 }
233 
234 ////////////////////////////////////////////////////////////////////////////////
235 /// Compute distance from inside point to surface of the hyperboloid.
236 
237 Double_t TGeoShapeAssembly::DistFromInside(const Double_t * /*point*/, const Double_t * /*dir*/, Int_t /*iact*/, Double_t /*step*/, Double_t * /*safe*/) const
238 {
239  Info("DistFromInside", "Cannot compute distance from inside the assembly (but from a component)");
240  return TGeoShape::Big();
241 }
242 
243 
244 ////////////////////////////////////////////////////////////////////////////////
245 /// compute distance from outside point to surface of the hyperboloid.
246 /// fVolume->SetNextNodeIndex(-1);
247 
248 Double_t TGeoShapeAssembly::DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
249 {
250 #ifdef TGEO_DEBUG
251  static int indent=0;
252  indent++;
253  TString sindent = "";
254  for (Int_t k=0; k<indent; k++) sindent += " ";
255  Int_t idebug = TGeoManager::GetVerboseLevel();
256 #endif
257  if (!fBBoxOK) ((TGeoShapeAssembly*)this)->ComputeBBox();
258  if (iact<3 && safe) {
259  *safe = Safety(point, kFALSE);
260 #ifdef TGEO_DEBUG
261  indent--;
262 #endif
263  if (iact==0) return TGeoShape::Big();
264  if ((iact==1) && (step<=*safe)) return TGeoShape::Big();
265 #ifdef TGEO_DEBUG
266  indent++;
267 #endif
268  }
269  // find distance to assembly
270  Double_t snext = 0.0;
271  Double_t dist;
272  Double_t stepmax = step;
273  Double_t pt[3];
274  Int_t i;
275  Bool_t found = kFALSE;
276  memcpy(pt,point,3*sizeof(Double_t));
277 #ifdef TGEO_DEBUG
278  if (idebug>4) printf("%s[%d] assembly %s checking distance to %d daughters...\n", sindent.Data(), indent, fVolume->GetName(), fVolume->GetNdaughters());
279 #endif
280 
281  if (!TGeoBBox::Contains(point)) {
282  snext = TGeoBBox::DistFromOutside(point, dir, 3, stepmax);
283  // Approach bounding box to minimize errors
284  snext = TMath::Min(0.01*snext, 1.E-6);
285 #ifdef TGEO_DEBUG
286  if (idebug>4 && snext > stepmax) printf("%s[%d] %s: bbox not crossed\n",sindent.Data(), indent, fVolume->GetName());
287  indent--;
288 #endif
289  if (snext > stepmax) return TGeoShape::Big();
290 #ifdef TGEO_DEBUG
291  indent++;
292 #endif
293  for (i=0; i<3; i++) pt[i] += snext*dir[i];
294 // if (Contains(pt)) {
295 #ifdef TGEO_DEBUG
296 // if (idebug>4) printf("%s[%d] Propagation to BBox of %s entered the component %s at %f\n", sindent.Data(), indent, fVolume->GetName(), fVolume->GetNode(fVolume->GetCurrentNodeIndex())->GetName(), snext);
297 // indent--;
298 #endif
299 // fVolume->SetNextNodeIndex(fVolume->GetCurrentNodeIndex());
300 // return snext;
301 // }
302 // snext += TGeoShape::Tolerance();
303  stepmax -= snext;
304  }
305  // Point represented by pt is now inside the bounding box - find distance to components
306  Int_t nd = fVolume->GetNdaughters();
307  TGeoNode *node;
308  Double_t lpoint[3],ldir[3];
309  TGeoVoxelFinder *voxels = fVolume->GetVoxels();
310  if (nd<5 || !voxels) {
311  for (i=0; i<nd; i++) {
312  node = fVolume->GetNode(i);
313  if (voxels && voxels->IsSafeVoxel(pt, i, stepmax)) continue;
314  node->MasterToLocal(pt, lpoint);
315  node->MasterToLocalVect(dir, ldir);
316 #ifdef TGEO_DEBUG
317  if (idebug>4) printf("%s[%d] distance to %s ...\n", sindent.Data(), indent, node->GetName());
318 #endif
319  dist = node->GetVolume()->GetShape()->DistFromOutside(lpoint, ldir, 3, stepmax);
320  if (dist<stepmax) {
321 #ifdef TGEO_DEBUG
322  if (idebug>4) {
323  printf("%s[%d] %s -> from local=(%19.16f, %19.16f, %19.16f, %19.16f, %19.16f, %19.16f)\n",
324  sindent.Data(), indent, fVolume->GetName(), lpoint[0],lpoint[1],lpoint[2],ldir[0],ldir[1],ldir[2]);
325  printf("%s[%d] -> (l)to: %s shape %s snext=%g\n", sindent.Data(), indent, node->GetName(),
326  node->GetVolume()->GetShape()->ClassName(), dist);
327  }
328 #endif
329 
330  stepmax = dist;
331  fVolume->SetNextNodeIndex(i);
332  found = kTRUE;
333  }
334  }
335  if (found) {
336  snext += stepmax;
337 #ifdef TGEO_DEBUG
338  if (idebug>4) printf("%s[%d] %s: found %s at %f\n", sindent.Data(), indent, fVolume->GetName(), fVolume->GetNode(fVolume->GetNextNodeIndex())->GetName(), snext);
339  indent--;
340 #endif
341  return snext;
342  }
343 #ifdef TGEO_DEBUG
344  if (idebug>4) printf("%s[%d] %s: no daughter crossed\n", sindent.Data(), indent, fVolume->GetName());
345  indent--;
346 #endif
347  return TGeoShape::Big();
348  }
349  // current volume is voxelized, first get current voxel
350  Int_t ncheck = 0;
351  Int_t *vlist = 0;
352  TGeoNavigator *nav = gGeoManager->GetCurrentNavigator();
353  TGeoStateInfo &td = *nav->GetCache()->GetInfo();
354 
355  voxels->SortCrossedVoxels(pt, dir, td);
356  while ((vlist=voxels->GetNextVoxel(pt, dir, ncheck, td))) {
357  for (i=0; i<ncheck; i++) {
358  node = fVolume->GetNode(vlist[i]);
359  node->MasterToLocal(pt, lpoint);
360  node->MasterToLocalVect(dir, ldir);
361 #ifdef TGEO_DEBUG
362  if (idebug>4) printf("%s[%d] distance to %s ...\n", sindent.Data(), indent, node->GetName());
363 #endif
364  dist = node->GetVolume()->GetShape()->DistFromOutside(lpoint, ldir, 3, stepmax);
365  if (dist<stepmax) {
366 #ifdef TGEO_DEBUG
367  if (idebug>4) {
368  printf("%s[%d] %s -> from local=(%19.16f, %19.16f, %19.16f, %19.16f, %19.16f, %19.16f)\n",
369  sindent.Data(), indent, fVolume->GetName(), lpoint[0],lpoint[1],lpoint[2], ldir[0],ldir[1],ldir[2]);
370  printf("%s[%d] -> to: %s shape %s snext=%g\n", sindent.Data(), indent, node->GetName(),
371  node->GetVolume()->GetShape()->ClassName(), dist);
372  }
373 #endif
374  stepmax = dist;
375  fVolume->SetNextNodeIndex(vlist[i]);
376  found = kTRUE;
377  }
378  }
379  }
380  nav->GetCache()->ReleaseInfo();
381  if (found) {
382  snext += stepmax;
383 #ifdef TGEO_DEBUG
384  if (idebug>4) printf("%s[%d] %s: found %s at %f\n", sindent.Data(), indent, fVolume->GetName(), fVolume->GetNode(fVolume->GetNextNodeIndex())->GetName(), snext);
385  indent--;
386 #endif
387  return snext;
388  }
389 #ifdef TGEO_DEBUG
390  if (idebug>4) printf("%s[%d] %s: no daughter crossed\n", sindent.Data(), indent, fVolume->GetName());
391  indent--;
392 #endif
393  return TGeoShape::Big();
394 }
395 
396 ////////////////////////////////////////////////////////////////////////////////
397 /// Cannot divide assemblies.
398 
399 TGeoVolume *TGeoShapeAssembly::Divide(TGeoVolume * /*voldiv*/, const char *divname, Int_t /*iaxis*/, Int_t /*ndiv*/,
400  Double_t /*start*/, Double_t /*step*/)
401 {
402  Error("Divide", "Assemblies cannot be divided. Division volume %s not created", divname);
403  return 0;
404 }
405 
406 ////////////////////////////////////////////////////////////////////////////////
407 /// in case shape has some negative parameters, these has to be computed
408 /// in order to fit the mother
409 
410 TGeoShape *TGeoShapeAssembly::GetMakeRuntimeShape(TGeoShape * /*mother*/, TGeoMatrix * /*mat*/) const
411 {
412  Error("GetMakeRuntimeShape", "Assemblies cannot be parametrized.");
413  return NULL;
414 }
415 
416 ////////////////////////////////////////////////////////////////////////////////
417 /// print shape parameters
418 
419 void TGeoShapeAssembly::InspectShape() const
420 {
421  printf("*** Shape %s: TGeoShapeAssembly ***\n", GetName());
422  printf(" Volume assembly %s with %i nodes\n", fVolume->GetName(), fVolume->GetNdaughters());
423  printf(" Bounding box:\n");
424  if (!fBBoxOK) ((TGeoShapeAssembly*)this)->ComputeBBox();
425  TGeoBBox::InspectShape();
426 }
427 
428 ////////////////////////////////////////////////////////////////////////////////
429 /// Fill TBuffer3D structure for segments and polygons.
430 
431 void TGeoShapeAssembly::SetSegsAndPols(TBuffer3D & /*buff*/) const
432 {
433  Error("SetSegsAndPols", "Drawing functions should not be called for assemblies, but rather for their content");
434 }
435 
436 ////////////////////////////////////////////////////////////////////////////////
437 /// computes the closest distance from given point to this shape, according
438 /// to option. The matching point on the shape is stored in spoint.
439 
440 Double_t TGeoShapeAssembly::Safety(const Double_t *point, Bool_t in) const
441 {
442  Double_t safety = TGeoShape::Big();
443  Double_t pt[3], loc[3];
444  if (!fBBoxOK) ((TGeoShapeAssembly*)this)->ComputeBBox();
445  if (in) {
446  Int_t index = fVolume->GetCurrentNodeIndex();
447  TGeoVolume *vol = fVolume;
448  TGeoNode *node;
449  memcpy(loc, point, 3*sizeof(Double_t));
450  while (index>=0) {
451  memcpy(pt, loc, 3*sizeof(Double_t));
452  node = vol->GetNode(index);
453  node->GetMatrix()->MasterToLocal(pt,loc);
454  vol = node->GetVolume();
455  index = vol->GetCurrentNodeIndex();
456  if (index<0) {
457  safety = vol->GetShape()->Safety(loc, in);
458  return safety;
459  }
460  }
461  return TGeoShape::Big();
462  }
463  Double_t safe;
464  TGeoVoxelFinder *voxels = fVolume->GetVoxels();
465  Int_t nd = fVolume->GetNdaughters();
466  Double_t *boxes = 0;
467  if (voxels) boxes = voxels->GetBoxes();
468  TGeoNode *node;
469  for (Int_t id=0; id<nd; id++) {
470  if (boxes && id>0) {
471  Int_t ist = 6*id;
472  Double_t dxyz = 0.;
473  Double_t dxyz0 = TMath::Abs(point[0]-boxes[ist+3])-boxes[ist];
474  if (dxyz0 > safety) continue;
475  Double_t dxyz1 = TMath::Abs(point[1]-boxes[ist+4])-boxes[ist+1];
476  if (dxyz1 > safety) continue;
477  Double_t dxyz2 = TMath::Abs(point[2]-boxes[ist+5])-boxes[ist+2];
478  if (dxyz2 > safety) continue;
479  if (dxyz0>0) dxyz+=dxyz0*dxyz0;
480  if (dxyz1>0) dxyz+=dxyz1*dxyz1;
481  if (dxyz2>0) dxyz+=dxyz2*dxyz2;
482  if (dxyz >= safety*safety) continue;
483  }
484  node = fVolume->GetNode(id);
485  safe = node->Safety(point, kFALSE);
486  if (safe<=0.0) return 0.0;
487  if (safe<safety) safety = safe;
488  }
489  return safety;
490 }
491 
492 ////////////////////////////////////////////////////////////////////////////////
493 /// Save a primitive as a C++ statement(s) on output stream "out".
494 
495 void TGeoShapeAssembly::SavePrimitive(std::ostream & /*out*/, Option_t * /*option*/ /*= ""*/)
496 {
497 }
498 
499 ////////////////////////////////////////////////////////////////////////////////
500 /// No mesh for assemblies.
501 
502 void TGeoShapeAssembly::SetPoints(Double_t * /*points*/) const
503 {
504  Error("SetPoints", "Drawing functions should not be called for assemblies, but rather for their content");
505 }
506 
507 ////////////////////////////////////////////////////////////////////////////////
508 /// No mesh for assemblies.
509 
510 void TGeoShapeAssembly::SetPoints(Float_t * /*points*/) const
511 {
512  Error("SetPoints", "Drawing functions should not be called for assemblies, but rather for their content");
513 }
514 
515 ////////////////////////////////////////////////////////////////////////////////
516 /// Returns numbers of vertices, segments and polygons composing the shape mesh.
517 
518 void TGeoShapeAssembly::GetMeshNumbers(Int_t &nvert, Int_t &nsegs, Int_t &npols) const
519 {
520  nvert = 0;
521  nsegs = 0;
522  npols = 0;
523 }
524 
525 ////////////////////////////////////////////////////////////////////////////////
526 /// Check the inside status for each of the points in the array.
527 /// Input: Array of point coordinates + vector size
528 /// Output: Array of Booleans for the inside of each point
529 
530 void TGeoShapeAssembly::Contains_v(const Double_t *points, Bool_t *inside, Int_t vecsize) const
531 {
532  for (Int_t i=0; i<vecsize; i++) inside[i] = Contains(&points[3*i]);
533 }
534 
535 ////////////////////////////////////////////////////////////////////////////////
536 /// Compute the normal for an array o points so that norm.dot.dir is positive
537 /// Input: Arrays of point coordinates and directions + vector size
538 /// Output: Array of normal directions
539 
540 void TGeoShapeAssembly::ComputeNormal_v(const Double_t *points, const Double_t *dirs, Double_t *norms, Int_t vecsize)
541 {
542  for (Int_t i=0; i<vecsize; i++) ComputeNormal(&points[3*i], &dirs[3*i], &norms[3*i]);
543 }
544 
545 ////////////////////////////////////////////////////////////////////////////////
546 /// Compute distance from array of input points having directions specified by dirs. Store output in dists
547 
548 void TGeoShapeAssembly::DistFromInside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step) const
549 {
550  for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromInside(&points[3*i], &dirs[3*i], 3, step[i]);
551 }
552 
553 ////////////////////////////////////////////////////////////////////////////////
554 /// Compute distance from array of input points having directions specified by dirs. Store output in dists
555 
556 void TGeoShapeAssembly::DistFromOutside_v(const Double_t *points, const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step) const
557 {
558  for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromOutside(&points[3*i], &dirs[3*i], 3, step[i]);
559 }
560 
561 ////////////////////////////////////////////////////////////////////////////////
562 /// Compute safe distance from each of the points in the input array.
563 /// Input: Array of point coordinates, array of statuses for these points, size of the arrays
564 /// Output: Safety values
565 
566 void TGeoShapeAssembly::Safety_v(const Double_t *points, const Bool_t *inside, Double_t *safe, Int_t vecsize) const
567 {
568  for (Int_t i=0; i<vecsize; i++) safe[i] = Safety(&points[3*i], inside[i]);
569 }