Logo ROOT   6.08/07
Reference Guide
TGeoBoolNode.cxx
Go to the documentation of this file.
1 // @(#):$Id$
2 // Author: Andrei Gheata 30/05/02
3 // TGeoBoolNode::Contains and parser implemented by Mihaela Gheata
4 
5 
6 /*************************************************************************
7  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
8  * All rights reserved. *
9  * *
10  * For the licensing terms see $ROOTSYS/LICENSE. *
11  * For the list of contributors see $ROOTSYS/README/CREDITS. *
12  *************************************************************************/
13 #include "TGeoBoolNode.h"
14 
15 #include "Riostream.h"
16 
17 #include "TThread.h"
18 #include "TVirtualPad.h"
19 #include "TVirtualViewer3D.h"
20 #include "TBuffer3D.h"
21 #include "TBuffer3DTypes.h"
22 #include "TMath.h"
23 #include "TGeoCompositeShape.h"
24 #include "TGeoMatrix.h"
25 #include "TGeoManager.h"
26 
27 /** \class TGeoBoolNode
28 \ingroup Geometry_classes
29 
30 Base class for Boolean operations between two shapes.
31 
32 A Boolean node describes a Boolean operation between 'left' and 'right'
33 shapes positioned with respect to an ARBITRARY reference frame. The boolean
34 node is referenced by a mother composite shape and its shape components may
35 be primitive but also composite shapes. The later situation leads to a binary
36 tree hierarchy. When the parent composite shape is used to create a volume,
37 the reference frame of the volume is chosen to match the frame in which
38 node shape components were defined.
39 
40 The positioned shape components may or may not be disjoint. The specific
41 implementations for Boolean nodes are:
42 
43  - TGeoUnion - representing the Boolean union of two positioned shapes
44  - TGeoSubtraction - representing the Boolean subtraction of two positioned shapes
45  - TGeoIntersection - representing the Boolean intersection of two positioned shapes
46 */
47 
49 
50 ////////////////////////////////////////////////////////////////////////////////
51 /// Constructor.
52 
54  fSelected(0)
55 {
56 }
57 
58 ////////////////////////////////////////////////////////////////////////////////
59 /// Destructor.
60 
62 {
63 }
64 
65 ////////////////////////////////////////////////////////////////////////////////
66 
68 {
70 /*
71  TThread::Lock();
72  if (tid >= fThreadSize) {
73  Error("GetThreadData", "Thread id=%d bigger than maximum declared thread number %d. \nUse TGeoManager::SetMaxThreads properly !!!",
74  tid, fThreadSize);
75  }
76  if (tid >= fThreadSize)
77  {
78  fThreadData.resize(tid + 1);
79  fThreadSize = tid + 1;
80  }
81  if (fThreadData[tid] == 0)
82  {
83  if (fThreadData[tid] == 0)
84  fThreadData[tid] = new ThreadData_t;
85  }
86  TThread::UnLock();
87 */
88  return *fThreadData[tid];
89 }
90 
91 ////////////////////////////////////////////////////////////////////////////////
92 
94 {
95  TThread::Lock();
96  std::vector<ThreadData_t*>::iterator i = fThreadData.begin();
97  while (i != fThreadData.end())
98  {
99  delete *i;
100  ++i;
101  }
102  fThreadData.clear();
103  fThreadSize = 0;
104  TThread::UnLock();
105 }
106 
107 ////////////////////////////////////////////////////////////////////////////////
108 /// Create thread data for n threads max.
109 
111 {
112  TThread::Lock();
113  fThreadData.resize(nthreads);
114  fThreadSize = nthreads;
115  for (Int_t tid=0; tid<nthreads; tid++) {
116  if (fThreadData[tid] == 0) {
117  fThreadData[tid] = new ThreadData_t;
118  }
119  }
120  // Propagate to components
121  if (fLeft) fLeft->CreateThreadData(nthreads);
122  if (fRight) fRight->CreateThreadData(nthreads);
123  TThread::UnLock();
124 }
125 
126 ////////////////////////////////////////////////////////////////////////////////
127 /// Set the selected branch.
128 
130 {
131  GetThreadData().fSelected = sel;
132 }
133 
134 ////////////////////////////////////////////////////////////////////////////////
135 /// Default constructor
136 
138 {
139  fLeft = 0;
140  fRight = 0;
141  fLeftMat = 0;
142  fRightMat = 0;
143  fNpoints = 0;
144  fPoints = 0;
145  fThreadSize = 0;
146  CreateThreadData(1);
147 }
148 
149 ////////////////////////////////////////////////////////////////////////////////
150 /// Constructor called by TGeoCompositeShape providing 2 subexpressions for the 2 branches.
151 
152 TGeoBoolNode::TGeoBoolNode(const char *expr1, const char *expr2)
153 {
154  fLeft = 0;
155  fRight = 0;
156  fLeftMat = 0;
157  fRightMat = 0;
158  fNpoints = 0;
159  fPoints = 0;
160  fThreadSize = 0;
161  CreateThreadData(1);
162  if (!MakeBranch(expr1, kTRUE)) {
163  return;
164  }
165  if (!MakeBranch(expr2, kFALSE)) {
166  return;
167  }
168 }
169 
170 ////////////////////////////////////////////////////////////////////////////////
171 /// Constructor providing left and right shapes and matrices (in the Boolean operation).
172 
174 {
175  fLeft = left;
176  fRight = right;
177  fLeftMat = lmat;
178  fNpoints = 0;
179  fPoints = 0;
180  fThreadSize = 0;
181  CreateThreadData(1);
183  else fLeftMat->RegisterYourself();
184  fRightMat = rmat;
186  else fRightMat->RegisterYourself();
187  if (!fLeft) {
188  Error("ctor", "left shape is NULL");
189  return;
190  }
191  if (!fRight) {
192  Error("ctor", "right shape is NULL");
193  return;
194  }
195 }
196 
197 ////////////////////////////////////////////////////////////////////////////////
198 /// Destructor.
199 /// --- deletion of components handled by TGeoManager class.
200 
202 {
203  if (fPoints) delete [] fPoints;
204  ClearThreadData();
205 }
206 
207 ////////////////////////////////////////////////////////////////////////////////
208 /// Expands the boolean expression either on left or right branch, creating
209 /// component elements (composite shapes and boolean nodes). Returns true on success.
210 
211 Bool_t TGeoBoolNode::MakeBranch(const char *expr, Bool_t left)
212 {
213  TString sleft, sright, stransf;
214  Int_t boolop = TGeoManager::Parse(expr, sleft, sright, stransf);
215  if (boolop<0) {
216  Error("MakeBranch", "invalid expression");
217  return kFALSE;
218  }
219  TGeoShape *shape = 0;
220  TGeoMatrix *mat;
221  TString newshape;
222 
223  if (stransf.Length() == 0) {
224  mat = gGeoIdentity;
225  } else {
226  mat = (TGeoMatrix*)gGeoManager->GetListOfMatrices()->FindObject(stransf.Data());
227  }
228  if (!mat) {
229  Error("MakeBranch", "transformation %s not found", stransf.Data());
230  return kFALSE;
231  }
232  switch (boolop) {
233  case 0:
234  // elementary shape
235  shape = (TGeoShape*)gGeoManager->GetListOfShapes()->FindObject(sleft.Data());
236  if (!shape) {
237  Error("MakeBranch", "shape %s not found", sleft.Data());
238  return kFALSE;
239  }
240  break;
241  case 1:
242  // composite shape - union
243  newshape = sleft;
244  newshape += "+";
245  newshape += sright;
246  shape = new TGeoCompositeShape(newshape.Data());
247  break;
248  case 2:
249  // composite shape - difference
250  newshape = sleft;
251  newshape += "-";
252  newshape += sright;
253  shape = new TGeoCompositeShape(newshape.Data());
254  break;
255  case 3:
256  // composite shape - intersection
257  newshape = sleft;
258  newshape += "*";
259  newshape += sright;
260  shape = new TGeoCompositeShape(newshape.Data());
261  break;
262  }
263  if (boolop && (!shape || !shape->IsValid())) {
264  Error("MakeBranch", "Shape %s not valid", newshape.Data());
265  if (shape) delete shape;
266  return kFALSE;
267  }
268  if (left) {
269  fLeft = shape;
270  fLeftMat = mat;
271  } else {
272  fRight = shape;
273  fRightMat = mat;
274  }
275  return kTRUE;
276 }
277 
278 ////////////////////////////////////////////////////////////////////////////////
279 /// Special schema for feeding the 3D buffers to the painter client.
280 
282 {
283  TVirtualViewer3D * viewer = gPad->GetViewer3D();
284  if (!viewer) return;
285 
286  // Components of composite shape hierarchies for local frame viewers are painted
287  // in coordinate frame of the top level composite shape. So we force
288  // conversion to this. See TGeoPainter::PaintNode for loading of GLMatrix.
289  Bool_t localFrame = kFALSE; //viewer->PreferLocalFrame();
290 
292  TGeoHMatrix mat;
293  mat = glmat; // keep a copy
294 
295  // Now perform fetch and add of the two components buffers.
296  // Note we assume that composite shapes are always completely added
297  // so don't bother to get addDaughters flag from viewer->AddObject()
298 
299  // Setup matrix and fetch/add the left component buffer
300  glmat->Multiply(fLeftMat);
301  //fLeft->Paint(option);
302  if (TGeoCompositeShape *left = dynamic_cast<TGeoCompositeShape *>(fLeft)) left->PaintComposite(option);
303  else {
304  const TBuffer3D & leftBuffer = fLeft->GetBuffer3D(TBuffer3D::kAll, localFrame);
305  viewer->AddObject(leftBuffer);
306  }
307 
308  // Setup matrix and fetch/add the right component buffer
309  *glmat = &mat;
310  glmat->Multiply(fRightMat);
311  //fRight->Paint(option);
312  if (TGeoCompositeShape *right = dynamic_cast<TGeoCompositeShape *>(fRight)) right->PaintComposite(option);
313  else {
314  const TBuffer3D & rightBuffer = fRight->GetBuffer3D(TBuffer3D::kAll, localFrame);
315  viewer->AddObject(rightBuffer);
316  }
317 
318  *glmat = &mat;
319 }
320 
321 ////////////////////////////////////////////////////////////////////////////////
322 /// Register all matrices of the boolean node and descendents.
323 
325 {
328  if (fLeft->IsComposite()) ((TGeoCompositeShape*)fLeft)->GetBoolNode()->RegisterMatrices();
329  if (fRight->IsComposite()) ((TGeoCompositeShape*)fRight)->GetBoolNode()->RegisterMatrices();
330 }
331 
332 ////////////////////////////////////////////////////////////////////////////////
333 /// Replace one of the matrices. Does not work with TGeoIdentity. Returns true
334 /// if replacement was successful.
335 
337 {
338  if (mat==gGeoIdentity || newmat==gGeoIdentity) {
339  Error("ReplaceMatrix", "Matrices should not be gGeoIdentity. Use default matrix constructor to represent identities.");
340  return kFALSE;
341  }
342  if (!mat || !newmat) {
343  Error("ReplaceMatrix", "Matrices should not be null pointers.");
344  return kFALSE;
345  }
346  Bool_t replaced = kFALSE;
347  if (fLeftMat == mat) {
348  fLeftMat = newmat;
349  replaced = kTRUE;
350  }
351  if (fRightMat == mat) {
352  fRightMat = newmat;
353  replaced = kTRUE;
354  }
355  return replaced;
356 }
357 
358 ////////////////////////////////////////////////////////////////////////////////
359 /// Save a primitive as a C++ statement(s) on output stream "out".
360 
361 void TGeoBoolNode::SavePrimitive(std::ostream &out, Option_t *option /*= ""*/)
362 {
363  fLeft->SavePrimitive(out,option);
364  fRight->SavePrimitive(out,option);
365  if (!fLeftMat->IsIdentity()) {
367  fLeftMat->SavePrimitive(out,option);
368  }
369  if (!fRightMat->IsIdentity()) {
371  fRightMat->SavePrimitive(out,option);
372  }
373 }
374 
375 ////////////////////////////////////////////////////////////////////////////////
376 /// Fill buffer with shape vertices.
377 
379 {
380  TGeoBoolNode *bn = (TGeoBoolNode*)this;
381  Int_t npoints = bn->GetNpoints();
382  memcpy(points, fPoints, 3*npoints*sizeof(Double_t));
383 }
384 
385 ////////////////////////////////////////////////////////////////////////////////
386 /// Fill buffer with shape vertices.
387 
389 {
390  TGeoBoolNode *bn = (TGeoBoolNode*)this;
391  Int_t npoints = bn->GetNpoints();
392  for (Int_t i=0; i<3*npoints; i++) points[i] = fPoints[i];
393 }
394 
395 ////////////////////////////////////////////////////////////////////////////////
396 /// Register size of this 3D object
397 
399 {
400  fLeft->Sizeof3D();
401  fRight->Sizeof3D();
402 }
403 
405 
406 ////////////////////////////////////////////////////////////////////////////////
407 /// Make a clone of this. Pointers are preserved.
408 
410 {
411  return new TGeoUnion(fLeft, fRight, fLeftMat, fRightMat);
412 }
413 
414 ////////////////////////////////////////////////////////////////////////////////
415 /// Paint method.
416 
418 {
419  TVirtualViewer3D *viewer = gPad->GetViewer3D();
420 
421  if (!viewer) {
422  Error("Paint", "gPad->GetViewer3D() returned 0, cannot work with composite!\n");
423  return;
424  }
425 
427 
428  TGeoBoolNode::Paint(option);
429 }
430 
431 ////////////////////////////////////////////////////////////////////////////////
432 /// Default constructor
433 
435 {
436 }
437 
438 ////////////////////////////////////////////////////////////////////////////////
439 /// Constructor
440 
441 TGeoUnion::TGeoUnion(const char *expr1, const char *expr2)
442  :TGeoBoolNode(expr1, expr2)
443 {
444 }
445 
446 ////////////////////////////////////////////////////////////////////////////////
447 /// Constructor providing pointers to components
448 
450  :TGeoBoolNode(left,right,lmat,rmat)
451 {
453  Fatal("TGeoUnion", "Unions with a half-space (%s + %s) not allowed", left->GetName(), right->GetName());
454  }
455 }
456 
457 ////////////////////////////////////////////////////////////////////////////////
458 /// Destructor
459 /// --- deletion of components handled by TGeoManager class.
460 
462 {
463 }
464 
465 ////////////////////////////////////////////////////////////////////////////////
466 /// Compute bounding box corresponding to a union of two shapes.
467 
469 {
470  if (((TGeoBBox*)fLeft)->IsNullBox()) fLeft->ComputeBBox();
471  if (((TGeoBBox*)fRight)->IsNullBox()) fRight->ComputeBBox();
472  Double_t vert[48];
473  Double_t pt[3];
474  Int_t i;
475  Double_t xmin, xmax, ymin, ymax, zmin, zmax;
476  xmin = ymin = zmin = TGeoShape::Big();
477  xmax = ymax = zmax = -TGeoShape::Big();
478  ((TGeoBBox*)fLeft)->SetBoxPoints(&vert[0]);
479  ((TGeoBBox*)fRight)->SetBoxPoints(&vert[24]);
480  for (i=0; i<8; i++) {
481  fLeftMat->LocalToMaster(&vert[3*i], &pt[0]);
482  if (pt[0]<xmin) xmin=pt[0];
483  if (pt[0]>xmax) xmax=pt[0];
484  if (pt[1]<ymin) ymin=pt[1];
485  if (pt[1]>ymax) ymax=pt[1];
486  if (pt[2]<zmin) zmin=pt[2];
487  if (pt[2]>zmax) zmax=pt[2];
488  }
489  for (i=8; i<16; i++) {
490  fRightMat->LocalToMaster(&vert[3*i], &pt[0]);
491  if (pt[0]<xmin) xmin=pt[0];
492  if (pt[0]>xmax) xmax=pt[0];
493  if (pt[1]<ymin) ymin=pt[1];
494  if (pt[1]>ymax) ymax=pt[1];
495  if (pt[2]<zmin) zmin=pt[2];
496  if (pt[2]>zmax) zmax=pt[2];
497  }
498  dx = 0.5*(xmax-xmin);
499  origin[0] = 0.5*(xmin+xmax);
500  dy = 0.5*(ymax-ymin);
501  origin[1] = 0.5*(ymin+ymax);
502  dz = 0.5*(zmax-zmin);
503  origin[2] = 0.5*(zmin+zmax);
504 }
505 
506 ////////////////////////////////////////////////////////////////////////////////
507 /// Find if a union of two shapes contains a given point
508 
510 {
511  Double_t local[3];
512  fLeftMat->MasterToLocal(point, &local[0]);
513  Bool_t inside = fLeft->Contains(&local[0]);
514  if (inside) return kTRUE;
515  fRightMat->MasterToLocal(point, &local[0]);
516  inside = fRight->Contains(&local[0]);
517  return inside;
518 }
519 
520 ////////////////////////////////////////////////////////////////////////////////
521 /// Normal computation in POINT. The orientation is chosen so that DIR.dot.NORM>0.
522 
523 void TGeoUnion::ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm)
524 {
525  ThreadData_t& td = GetThreadData();
526  norm[0] = norm[1] = 0.;
527  norm[2] = 1.;
528  Double_t local[3];
529  Double_t ldir[3], lnorm[3];
530  if (td.fSelected == 1) {
531  fLeftMat->MasterToLocal(point, local);
532  fLeftMat->MasterToLocalVect(dir, ldir);
533  fLeft->ComputeNormal(local,ldir,lnorm);
534  fLeftMat->LocalToMasterVect(lnorm, norm);
535  return;
536  }
537  if (td.fSelected == 2) {
538  fRightMat->MasterToLocal(point, local);
539  fRightMat->MasterToLocalVect(dir, ldir);
540  fRight->ComputeNormal(local,ldir,lnorm);
541  fRightMat->LocalToMasterVect(lnorm, norm);
542  return;
543  }
544  fLeftMat->MasterToLocal(point, local);
545  if (fLeft->Contains(local)) {
546  fLeftMat->MasterToLocalVect(dir, ldir);
547  fLeft->ComputeNormal(local,ldir,lnorm);
548  fLeftMat->LocalToMasterVect(lnorm, norm);
549  return;
550  }
551  fRightMat->MasterToLocal(point, local);
552  if (fRight->Contains(local)) {
553  fRightMat->MasterToLocalVect(dir, ldir);
554  fRight->ComputeNormal(local,ldir,lnorm);
555  fRightMat->LocalToMasterVect(lnorm, norm);
556  return;
557  }
558  // Propagate forward/backward to see which of the components is intersected first
559  local[0] = point[0] + 1E-5*dir[0];
560  local[1] = point[1] + 1E-5*dir[1];
561  local[2] = point[2] + 1E-5*dir[2];
562 
563  if (!Contains(local)) {
564  local[0] = point[0] - 1E-5*dir[0];
565  local[1] = point[1] - 1E-5*dir[1];
566  local[2] = point[2] - 1E-5*dir[2];
567  if (!Contains(local)) return;
568  }
569  ComputeNormal(local,dir,norm);
570 }
571 
572 ////////////////////////////////////////////////////////////////////////////////
573 /// Compute minimum distance to shape vertices.
574 
576 {
577  return 9999;
578 }
579 
580 ////////////////////////////////////////////////////////////////////////////////
581 /// Computes distance from a given point inside the shape to its boundary.
582 
584  Double_t step, Double_t *safe) const
585 {
586  if (iact<3 && safe) {
587  // compute safe distance
588  *safe = Safety(point,kTRUE);
589  if (iact==0) return TGeoShape::Big();
590  if (iact==1 && step<*safe) return TGeoShape::Big();
591  }
592 
593  Double_t local[3], local1[3], master[3], ldir[3], rdir[3], pushed[3];
594  memcpy(master, point, 3*sizeof(Double_t));
595  Int_t i;
596  TGeoBoolNode *node = (TGeoBoolNode*)this;
597  Double_t d1=0., d2=0., snxt=0., eps=0.;
598  fLeftMat->MasterToLocalVect(dir, ldir);
599  fRightMat->MasterToLocalVect(dir, rdir);
600  fLeftMat->MasterToLocal(point, local);
601  Bool_t inside1 = fLeft->Contains(local);
602  if (inside1) d1 = fLeft->DistFromInside(local, ldir, 3);
603  else memcpy(local1, local, 3*sizeof(Double_t));
604  fRightMat->MasterToLocal(point, local);
605  Bool_t inside2 = fRight->Contains(local);
606  if (inside2) d2 = fRight->DistFromInside(local, rdir, 3);
607  if (!(inside1 | inside2)) {
608  // This is a pathological case when the point is on the boundary
609  d1 = fLeft->DistFromOutside(local1, ldir, 3);
610  if (d1<1.E-3) {
611  eps = d1+TGeoShape::Tolerance();
612  for (i=0; i<3; i++) local1[i] += eps*ldir[i];
613  inside1 = kTRUE;
614  d1 = fLeft->DistFromInside(local1, ldir, 3);
615  d1 += eps;
616  } else {
617  d2 = fRight->DistFromOutside(local, rdir, 3);
618  if (d2<1.E-3) {
619  eps = d2+TGeoShape::Tolerance();
620  for (i=0; i<3; i++) local[i] += eps*rdir[i];
621  inside2 = kTRUE;
622  d2 = fRight->DistFromInside(local, rdir, 3);
623  d2 += eps;
624  }
625  }
626  }
627  while (inside1 || inside2) {
628  if (inside1 && inside2) {
629  if (d1<d2) {
630  snxt += d1;
631  node->SetSelected(1);
632  // propagate to exit of left shape
633  inside1 = kFALSE;
634  for (i=0; i<3; i++) master[i] += d1*dir[i];
635  // check if propagated point is in right shape
636  fRightMat->MasterToLocal(master, local);
637  inside2 = fRight->Contains(local);
638  if (!inside2) return snxt;
639  d2 = fRight->DistFromInside(local, rdir, 3);
640  if (d2 < TGeoShape::Tolerance()) return snxt;
641  } else {
642  snxt += d2;
643  node->SetSelected(2);
644  // propagate to exit of right shape
645  inside2 = kFALSE;
646  for (i=0; i<3; i++) master[i] += d2*dir[i];
647  // check if propagated point is in left shape
648  fLeftMat->MasterToLocal(master, local);
649  inside1 = fLeft->Contains(local);
650  if (!inside1) return snxt;
651  d1 = fLeft->DistFromInside(local, ldir, 3);
652  if (d1 < TGeoShape::Tolerance()) return snxt;
653  }
654  }
655  if (inside1) {
656  snxt += d1;
657  node->SetSelected(1);
658  // propagate to exit of left shape
659  inside1 = kFALSE;
660  for (i=0; i<3; i++) {
661  master[i] += d1*dir[i];
662  pushed[i] = master[i]+(1.+d1)*TGeoShape::Tolerance()*dir[i];
663  }
664  // check if propagated point is in right shape
665  fRightMat->MasterToLocal(pushed, local);
666  inside2 = fRight->Contains(local);
667  if (!inside2) return snxt;
668  d2 = fRight->DistFromInside(local, rdir, 3);
669  if (d2 < TGeoShape::Tolerance()) return snxt;
670  d2 += (1.+d1)*TGeoShape::Tolerance();
671  }
672  if (inside2) {
673  snxt += d2;
674  node->SetSelected(2);
675  // propagate to exit of right shape
676  inside2 = kFALSE;
677  for (i=0; i<3; i++) {
678  master[i] += d2*dir[i];
679  pushed[i] = master[i]+(1.+d2)*TGeoShape::Tolerance()*dir[i];
680  }
681  // check if propagated point is in left shape
682  fLeftMat->MasterToLocal(pushed, local);
683  inside1 = fLeft->Contains(local);
684  if (!inside1) return snxt;
685  d1 = fLeft->DistFromInside(local, ldir, 3);
686  if (d1 < TGeoShape::Tolerance()) return snxt;
687  d1 += (1.+d2)*TGeoShape::Tolerance();
688  }
689  }
690  return snxt;
691 }
692 
693 ////////////////////////////////////////////////////////////////////////////////
694 /// Compute distance from a given outside point to the shape.
695 
697  Double_t step, Double_t *safe) const
698 {
699  if (iact<3 && safe) {
700  // compute safe distance
701  *safe = Safety(point,kFALSE);
702  if (iact==0) return TGeoShape::Big();
703  if (iact==1 && step<*safe) return TGeoShape::Big();
704  }
705  TGeoBoolNode *node = (TGeoBoolNode*)this;
706  Double_t local[3], ldir[3], rdir[3];
707  Double_t d1, d2, snxt;
708  fLeftMat->MasterToLocal(point, &local[0]);
709  fLeftMat->MasterToLocalVect(dir, &ldir[0]);
710  fRightMat->MasterToLocalVect(dir, &rdir[0]);
711  d1 = fLeft->DistFromOutside(&local[0], &ldir[0], iact, step, safe);
712  fRightMat->MasterToLocal(point, &local[0]);
713  d2 = fRight->DistFromOutside(&local[0], &rdir[0], iact, step, safe);
714  if (d1<d2) {
715  snxt = d1;
716  node->SetSelected(1);
717  } else {
718  snxt = d2;
719  node->SetSelected(2);
720  }
721  return snxt;
722 }
723 
724 ////////////////////////////////////////////////////////////////////////////////
725 /// Returns number of vertices for the composite shape described by this union.
726 
728 {
729  Int_t itot=0;
730  Double_t point[3];
731  Double_t tolerance = TGeoShape::Tolerance();
732  if (fNpoints) return fNpoints;
733  // Local points for the left shape
734  Int_t nleft = fLeft->GetNmeshVertices();
735  Double_t *points1 = new Double_t[3*nleft];
736  fLeft->SetPoints(points1);
737  // Local points for the right shape
738  Int_t nright = fRight->GetNmeshVertices();
739  Double_t *points2 = new Double_t[3*nright];
740  fRight->SetPoints(points2);
741  Double_t *points = new Double_t[3*(nleft+nright)];
742  for (Int_t i=0; i<nleft; i++) {
743  if (TMath::Abs(points1[3*i])<tolerance && TMath::Abs(points1[3*i+1])<tolerance) continue;
744  fLeftMat->LocalToMaster(&points1[3*i], &points[3*itot]);
745  fRightMat->MasterToLocal(&points[3*itot], point);
746  if (!fRight->Contains(point)) itot++;
747  }
748  for (Int_t i=0; i<nright; i++) {
749  if (TMath::Abs(points2[3*i])<tolerance && TMath::Abs(points2[3*i+1])<tolerance) continue;
750  fRightMat->LocalToMaster(&points2[3*i], &points[3*itot]);
751  fLeftMat->MasterToLocal(&points[3*itot], point);
752  if (!fLeft->Contains(point)) itot++;
753  }
754  fNpoints = itot;
755  fPoints = new Double_t[3*fNpoints];
756  memcpy(fPoints, points, 3*fNpoints*sizeof(Double_t));
757  delete [] points1;
758  delete [] points2;
759  delete [] points;
760  return fNpoints;
761 }
762 
763 ////////////////////////////////////////////////////////////////////////////////
764 /// Compute safety distance for a union node;
765 
766 Double_t TGeoUnion::Safety(const Double_t *point, Bool_t in) const
767 {
768  Double_t local1[3], local2[3];
769  fLeftMat->MasterToLocal(point,local1);
770  Bool_t in1 = fLeft->Contains(local1);
771  fRightMat->MasterToLocal(point,local2);
772  Bool_t in2 = fRight->Contains(local2);
773  Bool_t intrue = in1 | in2;
774  if (intrue^in) return 0.0;
775  Double_t saf1 = fLeft->Safety(local1, in1);
776  Double_t saf2 = fRight->Safety(local2, in2);
777  if (in1 && in2) return TMath::Min(saf1, saf2);
778  if (in1) return saf1;
779  if (in2) return saf2;
780  return TMath::Min(saf1,saf2);
781 }
782 
783 ////////////////////////////////////////////////////////////////////////////////
784 /// Save a primitive as a C++ statement(s) on output stream "out".
785 
786 void TGeoUnion::SavePrimitive(std::ostream &out, Option_t *option /*= ""*/)
787 {
788  TGeoBoolNode::SavePrimitive(out,option);
789  out << " pBoolNode = new TGeoUnion(";
790  out << fLeft->GetPointerName() << ",";
791  out << fRight->GetPointerName() << ",";
792  if (!fLeftMat->IsIdentity()) out << fLeftMat->GetPointerName() << ",";
793  else out << "0,";
794  if (!fRightMat->IsIdentity()) out << fRightMat->GetPointerName() << ");" << std::endl;
795  else out << "0);" << std::endl;
796 }
797 
798 ////////////////////////////////////////////////////////////////////////////////
799 /// Register 3D size of this shape.
800 
802 {
804 }
805 
806 
808 
809 ////////////////////////////////////////////////////////////////////////////////
810 /// Make a clone of this. Pointers are preserved.
811 
813 {
815 }
816 
817 ////////////////////////////////////////////////////////////////////////////////
818 /// Paint method.
819 
821 {
822  TVirtualViewer3D *viewer = gPad->GetViewer3D();
823 
824  if (!viewer) {
825  Error("Paint", "gPad->GetViewer3D() returned 0, cannot work with composite!\n");
826  return;
827  }
828 
830 
831  TGeoBoolNode::Paint(option);
832 }
833 
834 ////////////////////////////////////////////////////////////////////////////////
835 /// Default constructor
836 
838 {
839 }
840 
841 ////////////////////////////////////////////////////////////////////////////////
842 /// Constructor
843 
844 TGeoSubtraction::TGeoSubtraction(const char *expr1, const char *expr2)
845  :TGeoBoolNode(expr1, expr2)
846 {
847 }
848 
849 ////////////////////////////////////////////////////////////////////////////////
850 /// Constructor providing pointers to components
851 
853  :TGeoBoolNode(left,right,lmat,rmat)
854 {
856  Fatal("TGeoSubstraction", "Subtractions from a half-space (%s) not allowed", left->GetName());
857  }
858 }
859 
860 ////////////////////////////////////////////////////////////////////////////////
861 /// Destructor
862 /// --- deletion of components handled by TGeoManager class.
863 
865 {
866 }
867 
868 ////////////////////////////////////////////////////////////////////////////////
869 /// Compute bounding box corresponding to a subtraction of two shapes.
870 
872 {
873  TGeoBBox *box = (TGeoBBox*)fLeft;
874  if (box->IsNullBox()) fLeft->ComputeBBox();
875  Double_t vert[24];
876  Double_t pt[3];
877  Int_t i;
878  Double_t xmin, xmax, ymin, ymax, zmin, zmax;
879  xmin = ymin = zmin = TGeoShape::Big();
880  xmax = ymax = zmax = -TGeoShape::Big();
881  box->SetBoxPoints(&vert[0]);
882  for (i=0; i<8; i++) {
883  fLeftMat->LocalToMaster(&vert[3*i], &pt[0]);
884  if (pt[0]<xmin) xmin=pt[0];
885  if (pt[0]>xmax) xmax=pt[0];
886  if (pt[1]<ymin) ymin=pt[1];
887  if (pt[1]>ymax) ymax=pt[1];
888  if (pt[2]<zmin) zmin=pt[2];
889  if (pt[2]>zmax) zmax=pt[2];
890  }
891  dx = 0.5*(xmax-xmin);
892  origin[0] = 0.5*(xmin+xmax);
893  dy = 0.5*(ymax-ymin);
894  origin[1] = 0.5*(ymin+ymax);
895  dz = 0.5*(zmax-zmin);
896  origin[2] = 0.5*(zmin+zmax);
897 }
898 
899 ////////////////////////////////////////////////////////////////////////////////
900 /// Normal computation in POINT. The orientation is chosen so that DIR.dot.NORM>0.
901 
903 {
904  ThreadData_t& td = GetThreadData();
905  norm[0] = norm[1] = 0.;
906  norm[2] = 1.;
907  Double_t local[3], ldir[3], lnorm[3];
908  if (td.fSelected == 1) {
909  fLeftMat->MasterToLocal(point, local);
910  fLeftMat->MasterToLocalVect(dir, ldir);
911  fLeft->ComputeNormal(local,ldir,lnorm);
912  fLeftMat->LocalToMasterVect(lnorm, norm);
913  return;
914  }
915  if (td.fSelected == 2) {
916  fRightMat->MasterToLocal(point, local);
917  fRightMat->MasterToLocalVect(dir, ldir);
918  fRight->ComputeNormal(local,ldir,lnorm);
919  fRightMat->LocalToMasterVect(lnorm, norm);
920  return;
921  }
922  fRightMat->MasterToLocal(point,local);
923  if (fRight->Contains(local)) {
924  fRightMat->MasterToLocalVect(dir,ldir);
925  fRight->ComputeNormal(local,ldir, lnorm);
926  fRightMat->LocalToMasterVect(lnorm,norm);
927  return;
928  }
929  fLeftMat->MasterToLocal(point,local);
930  if (!fLeft->Contains(local)) {
931  fLeftMat->MasterToLocalVect(dir,ldir);
932  fLeft->ComputeNormal(local,ldir, lnorm);
933  fLeftMat->LocalToMasterVect(lnorm,norm);
934  return;
935  }
936  // point is inside left shape, but not inside the right
937  local[0] = point[0]+1E-5*dir[0];
938  local[1] = point[1]+1E-5*dir[1];
939  local[2] = point[2]+1E-5*dir[2];
940  if (Contains(local)) {
941  local[0] = point[0]-1E-5*dir[0];
942  local[1] = point[1]-1E-5*dir[1];
943  local[2] = point[2]-1E-5*dir[2];
944  if (Contains(local)) return;
945  }
946  ComputeNormal(local,dir,norm);
947 }
948 
949 ////////////////////////////////////////////////////////////////////////////////
950 /// Find if a subtraction of two shapes contains a given point
951 
953 {
954  Double_t local[3];
955  fLeftMat->MasterToLocal(point, &local[0]);
956  Bool_t inside = fLeft->Contains(&local[0]);
957  if (!inside) return kFALSE;
958  fRightMat->MasterToLocal(point, &local[0]);
959  inside = !fRight->Contains(&local[0]);
960  return inside;
961 }
962 
963 ////////////////////////////////////////////////////////////////////////////////
964 /// Compute minimum distance to shape vertices
965 
967 {
968  return 9999;
969 }
970 
971 ////////////////////////////////////////////////////////////////////////////////
972 /// Compute distance from a given point inside to the shape boundary.
973 
975  Double_t step, Double_t *safe) const
976 {
977  if (iact<3 && safe) {
978  // compute safe distance
979  *safe = Safety(point,kTRUE);
980  if (iact==0) return TGeoShape::Big();
981  if (iact==1 && step<*safe) return TGeoShape::Big();
982  }
983  TGeoBoolNode *node = (TGeoBoolNode*)this;
984  Double_t local[3], ldir[3], rdir[3];
985  Double_t d1, d2, snxt=0.;
986  fLeftMat->MasterToLocal(point, &local[0]);
987  fLeftMat->MasterToLocalVect(dir, &ldir[0]);
988  fRightMat->MasterToLocalVect(dir, &rdir[0]);
989  d1 = fLeft->DistFromInside(&local[0], &ldir[0], iact, step, safe);
990  fRightMat->MasterToLocal(point, &local[0]);
991  d2 = fRight->DistFromOutside(&local[0], &rdir[0], iact, step, safe);
992  if (d1<d2) {
993  snxt = d1;
994  node->SetSelected(1);
995  } else {
996  snxt = d2;
997  node->SetSelected(2);
998  }
999  return snxt;
1000 }
1001 
1002 ////////////////////////////////////////////////////////////////////////////////
1003 /// Compute distance from a given point outside to the shape.
1004 
1006  Double_t step, Double_t *safe) const
1007 {
1008  if (iact<3 && safe) {
1009  // compute safe distance
1010  *safe = Safety(point,kFALSE);
1011  if (iact==0) return TGeoShape::Big();
1012  if (iact==1 && step<*safe) return TGeoShape::Big();
1013  }
1014  TGeoBoolNode *node = (TGeoBoolNode*)this;
1015  Double_t local[3], master[3], ldir[3], rdir[3];
1016  memcpy(&master[0], point, 3*sizeof(Double_t));
1017  Int_t i;
1018  Double_t d1, d2, snxt=0.;
1019  fRightMat->MasterToLocal(point, &local[0]);
1020  fLeftMat->MasterToLocalVect(dir, &ldir[0]);
1021  fRightMat->MasterToLocalVect(dir, &rdir[0]);
1022  // check if inside '-'
1023  Bool_t inside = fRight->Contains(&local[0]);
1024  Double_t epsil = 0.;
1025  while (1) {
1026  if (inside) {
1027  // propagate to outside of '-'
1028  node->SetSelected(2);
1029  d1 = fRight->DistFromInside(&local[0], &rdir[0], iact, step, safe);
1030  snxt += d1+epsil;
1031  for (i=0; i<3; i++) master[i] += (d1+1E-8)*dir[i];
1032  epsil = 1.E-8;
1033  // now master outside '-'; check if inside '+'
1034  fLeftMat->MasterToLocal(&master[0], &local[0]);
1035  if (fLeft->Contains(&local[0])) return snxt;
1036  }
1037  // master outside '-' and outside '+' ; find distances to both
1038  node->SetSelected(1);
1039  fLeftMat->MasterToLocal(&master[0], &local[0]);
1040  d2 = fLeft->DistFromOutside(&local[0], &ldir[0], iact, step, safe);
1041  if (d2>1E20) return TGeoShape::Big();
1042 
1043  fRightMat->MasterToLocal(&master[0], &local[0]);
1044  d1 = fRight->DistFromOutside(&local[0], &rdir[0], iact, step, safe);
1045  if (d2<d1-TGeoShape::Tolerance()) {
1046  snxt += d2+epsil;
1047  return snxt;
1048  }
1049  // propagate to '-'
1050  snxt += d1+epsil;
1051  for (i=0; i<3; i++) master[i] += (d1+1E-8)*dir[i];
1052  epsil = 1.E-8;
1053  // now inside '-' and not inside '+'
1054  fRightMat->MasterToLocal(&master[0], &local[0]);
1055  inside = kTRUE;
1056  }
1057 }
1058 
1059 ////////////////////////////////////////////////////////////////////////////////
1060 /// Returns number of vertices for the composite shape described by this subtraction.
1061 
1063 {
1064  Int_t itot=0;
1065  Double_t point[3];
1066  Double_t tolerance = TGeoShape::Tolerance();
1067  if (fNpoints) return fNpoints;
1068  Int_t nleft = fLeft->GetNmeshVertices();
1069  Int_t nright = fRight->GetNmeshVertices();
1070  Double_t *points = new Double_t[3*(nleft+nright)];
1071  Double_t *points1 = new Double_t[3*nleft];
1072  fLeft->SetPoints(points1);
1073  for (Int_t i=0; i<nleft; i++) {
1074  if (TMath::Abs(points1[3*i])<tolerance && TMath::Abs(points1[3*i+1])<tolerance) continue;
1075  fLeftMat->LocalToMaster(&points1[3*i], &points[3*itot]);
1076  fRightMat->MasterToLocal(&points[3*itot], point);
1077  if (!fRight->Contains(point)) itot++;
1078  }
1079  Double_t *points2 = new Double_t[3*nright];
1080  fRight->SetPoints(points2);
1081  for (Int_t i=0; i<nright; i++) {
1082  if (TMath::Abs(points2[3*i])<tolerance && TMath::Abs(points2[3*i+1])<tolerance) continue;
1083  fRightMat->LocalToMaster(&points2[3*i], &points[3*itot]);
1084  fLeftMat->MasterToLocal(&points[3*itot], point);
1085  if (fLeft->Contains(point)) itot++;
1086  }
1087  fNpoints = itot;
1088  fPoints = new Double_t[3*fNpoints];
1089  memcpy(fPoints, points, 3*fNpoints*sizeof(Double_t));
1090  delete [] points1;
1091  delete [] points2;
1092  delete [] points;
1093  return fNpoints;
1094 }
1095 
1096 ////////////////////////////////////////////////////////////////////////////////
1097 /// Compute safety distance for a union node;
1098 
1100 {
1101  Double_t local1[3], local2[3];
1102  fLeftMat->MasterToLocal(point,local1);
1103  Bool_t in1 = fLeft->Contains(local1);
1104  fRightMat->MasterToLocal(point,local2);
1105  Bool_t in2 = fRight->Contains(local2);
1106  Bool_t intrue = in1 && (!in2);
1107  if (in^intrue) return 0.0;
1108  Double_t saf1 = fLeft->Safety(local1, in1);
1109  Double_t saf2 = fRight->Safety(local2, in2);
1110  if (in1 && in2) return saf2;
1111  if (in1) return TMath::Min(saf1,saf2);
1112  if (in2) return TMath::Max(saf1,saf2);
1113  return saf1;
1114 }
1115 
1116 ////////////////////////////////////////////////////////////////////////////////
1117 /// Save a primitive as a C++ statement(s) on output stream "out".
1118 
1119 void TGeoSubtraction::SavePrimitive(std::ostream &out, Option_t *option /*= ""*/)
1120 {
1121  TGeoBoolNode::SavePrimitive(out,option);
1122  out << " pBoolNode = new TGeoSubtraction(";
1123  out << fLeft->GetPointerName() << ",";
1124  out << fRight->GetPointerName() << ",";
1125  if (!fLeftMat->IsIdentity()) out << fLeftMat->GetPointerName() << ",";
1126  else out << "0,";
1127  if (!fRightMat->IsIdentity()) out << fRightMat->GetPointerName() << ");" << std::endl;
1128  else out << "0);" << std::endl;
1129 }
1130 
1131 ////////////////////////////////////////////////////////////////////////////////
1132 /// Register 3D size of this shape.
1133 
1135 {
1137 }
1138 
1140 
1141 ////////////////////////////////////////////////////////////////////////////////
1142 /// Make a clone of this. Pointers are preserved.
1143 
1145 {
1147 }
1148 
1149 ////////////////////////////////////////////////////////////////////////////////
1150 /// Paint method.
1151 
1153 {
1154  TVirtualViewer3D *viewer = gPad->GetViewer3D();
1155 
1156  if (!viewer) {
1157  Error("Paint", "gPad->GetViewer3D() returned 0, cannot work with composite!\n");
1158  return;
1159  }
1160 
1162 
1163  TGeoBoolNode::Paint(option);
1164 }
1165 
1166 ////////////////////////////////////////////////////////////////////////////////
1167 /// Default constructor
1168 
1170 {
1171 }
1172 
1173 ////////////////////////////////////////////////////////////////////////////////
1174 /// Constructor
1175 
1176 TGeoIntersection::TGeoIntersection(const char *expr1, const char *expr2)
1177  :TGeoBoolNode(expr1, expr2)
1178 {
1179 }
1180 
1181 ////////////////////////////////////////////////////////////////////////////////
1182 /// Constructor providing pointers to components
1183 
1185  :TGeoBoolNode(left,right,lmat,rmat)
1186 {
1189  if (hs1 && hs2) Fatal("ctor", "cannot intersect two half-spaces: %s * %s", left->GetName(), right->GetName());
1190 }
1191 
1192 ////////////////////////////////////////////////////////////////////////////////
1193 /// Destructor
1194 /// --- deletion of components handled by TGeoManager class.
1195 
1197 {
1198 }
1199 
1200 ////////////////////////////////////////////////////////////////////////////////
1201 /// Compute bounding box corresponding to a intersection of two shapes.
1202 
1204 {
1207  Double_t vert[48];
1208  Double_t pt[3];
1209  Int_t i;
1210  Double_t xmin1, xmax1, ymin1, ymax1, zmin1, zmax1;
1211  Double_t xmin2, xmax2, ymin2, ymax2, zmin2, zmax2;
1212  xmin1 = ymin1 = zmin1 = xmin2 = ymin2 = zmin2 = TGeoShape::Big();
1213  xmax1 = ymax1 = zmax1 = xmax2 = ymax2 = zmax2 = -TGeoShape::Big();
1214  if (!hs1) {
1215  if (((TGeoBBox*)fLeft)->IsNullBox()) fLeft->ComputeBBox();
1216  ((TGeoBBox*)fLeft)->SetBoxPoints(&vert[0]);
1217  for (i=0; i<8; i++) {
1218  fLeftMat->LocalToMaster(&vert[3*i], &pt[0]);
1219  if (pt[0]<xmin1) xmin1=pt[0];
1220  if (pt[0]>xmax1) xmax1=pt[0];
1221  if (pt[1]<ymin1) ymin1=pt[1];
1222  if (pt[1]>ymax1) ymax1=pt[1];
1223  if (pt[2]<zmin1) zmin1=pt[2];
1224  if (pt[2]>zmax1) zmax1=pt[2];
1225  }
1226  }
1227  if (!hs2) {
1228  if (((TGeoBBox*)fRight)->IsNullBox()) fRight->ComputeBBox();
1229  ((TGeoBBox*)fRight)->SetBoxPoints(&vert[24]);
1230  for (i=8; i<16; i++) {
1231  fRightMat->LocalToMaster(&vert[3*i], &pt[0]);
1232  if (pt[0]<xmin2) xmin2=pt[0];
1233  if (pt[0]>xmax2) xmax2=pt[0];
1234  if (pt[1]<ymin2) ymin2=pt[1];
1235  if (pt[1]>ymax2) ymax2=pt[1];
1236  if (pt[2]<zmin2) zmin2=pt[2];
1237  if (pt[2]>zmax2) zmax2=pt[2];
1238  }
1239  }
1240  if (hs1) {
1241  dx = 0.5*(xmax2-xmin2);
1242  origin[0] = 0.5*(xmax2+xmin2);
1243  dy = 0.5*(ymax2-ymin2);
1244  origin[1] = 0.5*(ymax2+ymin2);
1245  dz = 0.5*(zmax2-zmin2);
1246  origin[2] = 0.5*(zmax2+zmin2);
1247  return;
1248  }
1249  if (hs2) {
1250  dx = 0.5*(xmax1-xmin1);
1251  origin[0] = 0.5*(xmax1+xmin1);
1252  dy = 0.5*(ymax1-ymin1);
1253  origin[1] = 0.5*(ymax1+ymin1);
1254  dz = 0.5*(zmax1-zmin1);
1255  origin[2] = 0.5*(zmax1+zmin1);
1256  return;
1257  }
1258  Double_t sort[4];
1259  Int_t isort[4];
1260  sort[0] = xmin1;
1261  sort[1] = xmax1;
1262  sort[2] = xmin2;
1263  sort[3] = xmax2;
1264  TMath::Sort(4, &sort[0], &isort[0], kFALSE);
1265  if (isort[1]%2) {
1266  Warning("ComputeBBox", "shapes %s and %s do not intersect", fLeft->GetName(), fRight->GetName());
1267  dx = dy = dz = 0;
1268  memset(origin, 0, 3*sizeof(Double_t));
1269  return;
1270  }
1271  dx = 0.5*(sort[isort[2]]-sort[isort[1]]);
1272  origin[0] = 0.5*(sort[isort[1]]+sort[isort[2]]);
1273  sort[0] = ymin1;
1274  sort[1] = ymax1;
1275  sort[2] = ymin2;
1276  sort[3] = ymax2;
1277  TMath::Sort(4, &sort[0], &isort[0], kFALSE);
1278  if (isort[1]%2) {
1279  Warning("ComputeBBox", "shapes %s and %s do not intersect", fLeft->GetName(), fRight->GetName());
1280  dx = dy = dz = 0;
1281  memset(origin, 0, 3*sizeof(Double_t));
1282  return;
1283  }
1284  dy = 0.5*(sort[isort[2]]-sort[isort[1]]);
1285  origin[1] = 0.5*(sort[isort[1]]+sort[isort[2]]);
1286  sort[0] = zmin1;
1287  sort[1] = zmax1;
1288  sort[2] = zmin2;
1289  sort[3] = zmax2;
1290  TMath::Sort(4, &sort[0], &isort[0], kFALSE);
1291  if (isort[1]%2) {
1292  Warning("ComputeBBox", "shapes %s and %s do not intersect", fLeft->GetName(), fRight->GetName());
1293  dx = dy = dz = 0;
1294  memset(origin, 0, 3*sizeof(Double_t));
1295  return;
1296  }
1297  dz = 0.5*(sort[isort[2]]-sort[isort[1]]);
1298  origin[2] = 0.5*(sort[isort[1]]+sort[isort[2]]);
1299 }
1300 
1301 ////////////////////////////////////////////////////////////////////////////////
1302 /// Normal computation in POINT. The orientation is chosen so that DIR.dot.NORM>0.
1303 
1305 {
1306  ThreadData_t& td = GetThreadData();
1307  Double_t local[3], ldir[3], lnorm[3];
1308  norm[0] = norm[1] = 0.;
1309  norm[2] = 1.;
1310  if (td.fSelected == 1) {
1311  fLeftMat->MasterToLocal(point, local);
1312  fLeftMat->MasterToLocalVect(dir, ldir);
1313  fLeft->ComputeNormal(local,ldir,lnorm);
1314  fLeftMat->LocalToMasterVect(lnorm, norm);
1315  return;
1316  }
1317  if (td.fSelected == 2) {
1318  fRightMat->MasterToLocal(point, local);
1319  fRightMat->MasterToLocalVect(dir, ldir);
1320  fRight->ComputeNormal(local,ldir,lnorm);
1321  fRightMat->LocalToMasterVect(lnorm, norm);
1322  return;
1323  }
1324  fLeftMat->MasterToLocal(point,local);
1325  if (!fLeft->Contains(local)) {
1326  fLeftMat->MasterToLocalVect(dir,ldir);
1327  fLeft->ComputeNormal(local,ldir,lnorm);
1328  fLeftMat->LocalToMasterVect(lnorm,norm);
1329  return;
1330  }
1331  fRightMat->MasterToLocal(point,local);
1332  if (!fRight->Contains(local)) {
1333  fRightMat->MasterToLocalVect(dir,ldir);
1334  fRight->ComputeNormal(local,ldir,lnorm);
1335  fRightMat->LocalToMasterVect(lnorm,norm);
1336  return;
1337  }
1338  // point is inside intersection.
1339  local[0] = point[0] + 1E-5*dir[0];
1340  local[1] = point[1] + 1E-5*dir[1];
1341  local[2] = point[2] + 1E-5*dir[2];
1342  if (Contains(local)) {
1343  local[0] = point[0] - 1E-5*dir[0];
1344  local[1] = point[1] - 1E-5*dir[1];
1345  local[2] = point[2] - 1E-5*dir[2];
1346  if (Contains(local)) return;
1347  }
1348  ComputeNormal(local,dir,norm);
1349 }
1350 
1351 ////////////////////////////////////////////////////////////////////////////////
1352 /// Find if a intersection of two shapes contains a given point
1353 
1355 {
1356  Double_t local[3];
1357  fLeftMat->MasterToLocal(point, &local[0]);
1358  Bool_t inside = fLeft->Contains(&local[0]);
1359  if (!inside) return kFALSE;
1360  fRightMat->MasterToLocal(point, &local[0]);
1361  inside = fRight->Contains(&local[0]);
1362  return inside;
1363 }
1364 
1365 ////////////////////////////////////////////////////////////////////////////////
1366 /// Compute minimum distance to shape vertices
1367 
1369 {
1370  return 9999;
1371 }
1372 
1373 ////////////////////////////////////////////////////////////////////////////////
1374 /// Compute distance from a given point inside to the shape boundary.
1375 
1377  Double_t step, Double_t *safe) const
1378 {
1379  if (iact<3 && safe) {
1380  // compute safe distance
1381  *safe = Safety(point,kTRUE);
1382  if (iact==0) return TGeoShape::Big();
1383  if (iact==1 && step<*safe) return TGeoShape::Big();
1384  }
1385  TGeoBoolNode *node = (TGeoBoolNode*)this;
1386  Double_t local[3], ldir[3], rdir[3];
1387  Double_t d1, d2, snxt=0.;
1388  fLeftMat->MasterToLocal(point, &local[0]);
1389  fLeftMat->MasterToLocalVect(dir, &ldir[0]);
1390  fRightMat->MasterToLocalVect(dir, &rdir[0]);
1391  d1 = fLeft->DistFromInside(&local[0], &ldir[0], iact, step, safe);
1392  fRightMat->MasterToLocal(point, &local[0]);
1393  d2 = fRight->DistFromInside(&local[0], &rdir[0], iact, step, safe);
1394  if (d1<d2) {
1395  snxt = d1;
1396  node->SetSelected(1);
1397  } else {
1398  snxt = d2;
1399  node->SetSelected(2);
1400  }
1401  return snxt;
1402 }
1403 
1404 ////////////////////////////////////////////////////////////////////////////////
1405 /// Compute distance from a given point outside to the shape.
1406 
1408  Double_t step, Double_t *safe) const
1409 {
1411  if (iact<3 && safe) {
1412  // compute safe distance
1413  *safe = Safety(point,kFALSE);
1414  if (iact==0) return TGeoShape::Big();
1415  if (iact==1 && step<*safe) return TGeoShape::Big();
1416  }
1417  TGeoBoolNode *node = (TGeoBoolNode*)this;
1418  Double_t lpt[3], rpt[3], master[3], ldir[3], rdir[3];
1419  memcpy(master, point, 3*sizeof(Double_t));
1420  Int_t i;
1421  Double_t d1 = 0.;
1422  Double_t d2 = 0.;
1423  fLeftMat->MasterToLocal(point, lpt);
1424  fRightMat->MasterToLocal(point, rpt);
1425  fLeftMat->MasterToLocalVect(dir, ldir);
1426  fRightMat->MasterToLocalVect(dir, rdir);
1427  Bool_t inleft = fLeft->Contains(lpt);
1428  Bool_t inright = fRight->Contains(rpt);
1429  node->SetSelected(0);
1430  Double_t snext = 0.0;
1431  if (inleft && inright) {
1432  // It is vey likely to have a numerical issue and the point should
1433  // be logically outside one of the shapes
1434  d1 = fLeft->DistFromInside(lpt,ldir,3);
1435  d2 = fRight->DistFromInside(rpt,rdir,3);
1436  if (d1<1.E-3) inleft = kFALSE;
1437  if (d2<1.E-3) inright = kFALSE;
1438  if (inleft && inright) return snext;
1439  }
1440 
1441  while (1) {
1442  d1 = d2 = 0;
1443  if (!inleft) {
1444  d1 = fLeft->DistFromOutside(lpt,ldir,3);
1445  d1 = TMath::Max(d1,tol);
1446  if (d1>1E20) return TGeoShape::Big();
1447  }
1448  if (!inright) {
1449  d2 = fRight->DistFromOutside(rpt,rdir,3);
1450  d2 = TMath::Max(d2,tol);
1451  if (d2>1E20) return TGeoShape::Big();
1452  }
1453 
1454  if (d1>d2) {
1455  // propagate to left shape
1456  snext += d1;
1457  node->SetSelected(1);
1458  inleft = kTRUE;
1459  for (i=0; i<3; i++) master[i] += d1*dir[i];
1460  fRightMat->MasterToLocal(master,rpt);
1461  // Push rpt to avoid a bad boundary condition
1462  for (i=0; i<3; i++) rpt[i] += tol*rdir[i];
1463  // check if propagated point is inside right shape
1464  inright = fRight->Contains(rpt);
1465  if (inright) return snext;
1466  // here inleft=true, inright=false
1467  } else {
1468  // propagate to right shape
1469  snext += d2;
1470  node->SetSelected(2);
1471  inright = kTRUE;
1472  for (i=0; i<3; i++) master[i] += d2*dir[i];
1473  fLeftMat->MasterToLocal(master,lpt);
1474  // Push lpt to avoid a bad boundary condition
1475  for (i=0; i<3; i++) lpt[i] += tol*ldir[i];
1476  // check if propagated point is inside left shape
1477  inleft = fLeft->Contains(lpt);
1478  if (inleft) return snext;
1479  // here inleft=false, inright=true
1480  }
1481  }
1482  return snext;
1483 }
1484 
1485 ////////////////////////////////////////////////////////////////////////////////
1486 /// Returns number of vertices for the composite shape described by this intersection.
1487 
1489 {
1490  Int_t itot=0;
1491  Double_t point[3];
1492  Double_t tolerance = TGeoShape::Tolerance();
1493  if (fNpoints) return fNpoints;
1494  Int_t nleft = fLeft->GetNmeshVertices();
1495  Int_t nright = fRight->GetNmeshVertices();
1496  Double_t *points = new Double_t[3*(nleft+nright)];
1497  Double_t *points1 = new Double_t[3*nleft];
1498  fLeft->SetPoints(points1);
1499  for (Int_t i=0; i<nleft; i++) {
1500  if (TMath::Abs(points1[3*i])<tolerance && TMath::Abs(points1[3*i+1])<tolerance) continue;
1501  fLeftMat->LocalToMaster(&points1[3*i], &points[3*itot]);
1502  fRightMat->MasterToLocal(&points[3*itot], point);
1503  if (fRight->Contains(point)) itot++;
1504  }
1505  Double_t *points2 = new Double_t[3*nright];
1506  fRight->SetPoints(points2);
1507  for (Int_t i=0; i<nright; i++) {
1508  if (TMath::Abs(points2[3*i])<tolerance && TMath::Abs(points2[3*i+1])<tolerance) continue;
1509  fRightMat->LocalToMaster(&points2[3*i], &points[3*itot]);
1510  fLeftMat->MasterToLocal(&points[3*itot], point);
1511  if (fLeft->Contains(point)) itot++;
1512  }
1513  fNpoints = itot;
1514  fPoints = new Double_t[3*fNpoints];
1515  memcpy(fPoints, points, 3*fNpoints*sizeof(Double_t));
1516  delete [] points1;
1517  delete [] points2;
1518  delete [] points;
1519  return fNpoints;
1520 }
1521 
1522 ////////////////////////////////////////////////////////////////////////////////
1523 /// Compute safety distance for a union node;
1524 
1526 {
1527  Double_t local1[3], local2[3];
1528  fLeftMat->MasterToLocal(point,local1);
1529  Bool_t in1 = fLeft->Contains(local1);
1530  fRightMat->MasterToLocal(point,local2);
1531  Bool_t in2 = fRight->Contains(local2);
1532  Bool_t intrue = in1 & in2;
1533  if (in^intrue) return 0.0;
1534  Double_t saf1 = fLeft->Safety(local1, in1);
1535  Double_t saf2 = fRight->Safety(local2, in2);
1536  if (in1 && in2) return TMath::Min(saf1, saf2);
1537  if (in1) return saf2;
1538  if (in2) return saf1;
1539  return TMath::Max(saf1,saf2);
1540 }
1541 
1542 ////////////////////////////////////////////////////////////////////////////////
1543 /// Save a primitive as a C++ statement(s) on output stream "out".
1544 
1545 void TGeoIntersection::SavePrimitive(std::ostream &out, Option_t *option /*= ""*/)
1546 {
1547  TGeoBoolNode::SavePrimitive(out,option);
1548  out << " pBoolNode = new TGeoIntersection(";
1549  out << fLeft->GetPointerName() << ",";
1550  out << fRight->GetPointerName() << ",";
1551  if (!fLeftMat->IsIdentity()) out << fLeftMat->GetPointerName() << ",";
1552  else out << "0,";
1553  if (!fRightMat->IsIdentity()) out << fRightMat->GetPointerName() << ");" << std::endl;
1554  else out << "0);" << std::endl;
1555 }
1556 
1557 ////////////////////////////////////////////////////////////////////////////////
1558 /// Register 3D size of this shape.
1559 
1561 {
1563 }
virtual Double_t DistFromInside(const Double_t *point, const Double_t *dir, Int_t iact=1, Double_t step=0, Double_t *safe=0) const
Compute distance from a given point inside to the shape boundary.
virtual Int_t DistanceToPrimitive(Int_t px, Int_t py)
Compute minimum distance to shape vertices.
virtual void Sizeof3D() const =0
virtual Int_t GetNpoints()
Returns number of vertices for the composite shape described by this subtraction. ...
float xmin
Definition: THbookFile.cxx:93
TGeoUnion()
Default constructor.
virtual void MasterToLocalVect(const Double_t *master, Double_t *local) const
convert a point by multiplying its column vector (x, y, z, 1) to matrix
Definition: TGeoMatrix.cxx:481
virtual ~TGeoUnion()
Destructor — deletion of components handled by TGeoManager class.
virtual Double_t DistFromInside(const Double_t *point, const Double_t *dir, Int_t iact=1, Double_t step=0, Double_t *safe=0) const
Compute distance from a given point inside to the shape boundary.
#define snext(osub1, osub2)
Definition: triangle.c:1167
Box class.
Definition: TGeoBBox.h:19
virtual void ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm)
Normal computation in POINT. The orientation is chosen so that DIR.dot.NORM>0.
virtual void ComputeBBox(Double_t &dx, Double_t &dy, Double_t &dz, Double_t *origin)
Compute bounding box corresponding to a subtraction of two shapes.
Bool_t IsValid() const
Definition: TGeoShape.h:142
virtual void Sizeof3D() const
Register 3D size of this shape.
virtual void ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm)=0
float Float_t
Definition: RtypesCore.h:53
const char Option_t
Definition: RtypesCore.h:62
Geometrical transformation package.
Definition: TGeoMatrix.h:40
std::vector< ThreadData_t * > fThreadData
array of mesh points
Definition: TGeoBoolNode.h:54
float ymin
Definition: THbookFile.cxx:93
virtual Double_t Safety(const Double_t *point, Bool_t in=kTRUE) const
Compute safety distance for a union node;.
virtual void CreateThreadData(Int_t)
Definition: TGeoShape.h:70
void SetSelected(Int_t sel)
Set the selected branch.
virtual void SavePrimitive(std::ostream &out, Option_t *option="")
Save a primitive as a C++ statement(s) on output stream "out".
virtual void Paint(Option_t *option)
Paint method.
virtual Int_t DistanceToPrimitive(Int_t px, Int_t py)
Compute minimum distance to shape vertices.
TGeoIntersection()
Default constructor.
virtual void Sizeof3D() const
Register 3D size of this shape.
virtual Int_t GetNpoints()=0
virtual void Sizeof3D() const
Register 3D size of this shape.
Int_t fNpoints
Definition: TGeoBoolNode.h:51
Basic string class.
Definition: TString.h:137
virtual Bool_t Contains(const Double_t *point) const
Find if a union of two shapes contains a given point.
Matrix class used for computing global transformations Should NOT be used for node definition...
Definition: TGeoMatrix.h:410
void Multiply(const TGeoMatrix *right)
multiply to the right with an other transformation if right is identity matrix, just return ...
Short_t Min(Short_t a, Short_t b)
Definition: TMathBase.h:170
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
virtual void SetPoints(Double_t *points) const
Fill buffer with shape vertices.
const Bool_t kFALSE
Definition: Rtypes.h:92
static Int_t Parse(const char *expr, TString &expr1, TString &expr2, TString &expr3)
Parse a string boolean expression and do a syntax check.
void RegisterMatrices()
Register all matrices of the boolean node and descendents.
void box(Int_t pat, Double_t x1, Double_t y1, Double_t x2, Double_t y2)
Definition: fillpatterns.C:1
virtual TGeoBoolNode * MakeClone() const =0
Short_t Abs(Short_t d)
Definition: TMathBase.h:110
virtual void ComputeBBox()
Compute bounding box - nothing to do in this case.
Definition: TGeoBBox.cxx:333
virtual ~TGeoSubtraction()
Destructor — deletion of components handled by TGeoManager class.
virtual void ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm)
Normal computation in POINT. The orientation is chosen so that DIR.dot.NORM>0.
virtual Double_t Safety(const Double_t *point, Bool_t in=kTRUE) const
Compute safety distance for a union node;.
static Double_t Tolerance()
Definition: TGeoShape.h:93
virtual Bool_t Contains(const Double_t *point) const =0
TGeoMatrix * fLeftMat
Definition: TGeoBoolNode.h:49
Bool_t MakeBranch(const char *expr, Bool_t left)
Size for the navigation data array.
virtual void Paint(Option_t *option)
Special schema for feeding the 3D buffers to the painter client.
virtual TObject * FindObject(const char *name) const
Find an object in this collection using its name.
Definition: TObjArray.cxx:396
virtual TGeoBoolNode * MakeClone() const
Make a clone of this. Pointers are preserved.
virtual Int_t GetNpoints()
Returns number of vertices for the composite shape described by this union.
Bool_t IsIdentity() const
Definition: TGeoMatrix.h:77
void Sort(Index n, const Element *a, Index *index, Bool_t down=kTRUE)
Definition: TMath.h:989
virtual Double_t DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact=1, Double_t step=0, Double_t *safe=0) const
Compute distance from a given point outside to the shape.
Abstract 3D shapes viewer.
virtual void LocalToMasterVect(const Double_t *local, Double_t *master) const
convert a vector by multiplying its column vector (x, y, z, 1) to matrix inverse
Definition: TGeoMatrix.cxx:413
char * GetPointerName() const
Provide a pointer name containing uid.
Definition: TGeoMatrix.cxx:344
TGeoBoolNode()
Default constructor.
virtual void SetPoints(Double_t *points) const =0
void SetBoxPoints(Double_t *points) const
Fill box vertices to an array.
Definition: TGeoBBox.cxx:940
const char * GetPointerName() const
Provide a pointer name containing uid.
Definition: TGeoShape.cxx:701
virtual ~TGeoBoolNode()
Destructor.
virtual Double_t Safety(const Double_t *point, Bool_t in=kTRUE) const
Compute safety distance for a union node;.
point * points
Definition: X3DBuffer.c:20
Class handling Boolean composition of shapes.
virtual const char * GetName() const
Get the shape name.
Definition: TGeoShape.cxx:250
TGeoShape * fRight
Definition: TGeoBoolNode.h:48
TGeoSubtraction()
Default constructor.
virtual Double_t DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact=1, Double_t step=0, Double_t *safe=0) const
Compute distance from a given outside point to the shape.
float ymax
Definition: THbookFile.cxx:93
virtual Int_t GetNpoints()
Returns number of vertices for the composite shape described by this intersection.
const double tol
Base abstract class for all shapes.
Definition: TGeoShape.h:27
TPaveText * pt
TGeoShape * fLeft
Definition: TGeoBoolNode.h:47
Int_t fThreadSize
Navigation data per thread.
Definition: TGeoBoolNode.h:55
virtual Bool_t Contains(const Double_t *point) const
Find if a intersection of two shapes contains a given point.
virtual Double_t Safety(const Double_t *point, Bool_t in=kTRUE) const =0
virtual Bool_t IsComposite() const
Definition: TGeoShape.h:132
virtual Bool_t Contains(const Double_t *point) const
Find if a subtraction of two shapes contains a given point.
virtual const TBuffer3D & GetBuffer3D(Int_t reqSections, Bool_t localFrame) const
Stub implementation to avoid forcing implementation at this stage.
Definition: TGeoShape.cxx:691
virtual void SavePrimitive(std::ostream &out, Option_t *option="")
Save a primitive as a C++ statement(s) on output stream "out".
virtual Int_t GetNmeshVertices() const
Definition: TGeoShape.h:129
TObjArray * GetListOfShapes() const
Definition: TGeoManager.h:465
virtual Double_t DistFromInside(const Double_t *point, const Double_t *dir, Int_t iact=1, Double_t step=0, Double_t *safe=0) const
Computes distance from a given point inside the shape to its boundary.
virtual Int_t AddObject(const TBuffer3D &buffer, Bool_t *addChildren=0)=0
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:925
virtual void ComputeNormal(const Double_t *point, const Double_t *dir, Double_t *norm)
Normal computation in POINT. The orientation is chosen so that DIR.dot.NORM>0.
Ssiz_t Length() const
Definition: TString.h:390
virtual void RegisterYourself()
Register the matrix in the current manager, which will become the owner.
Definition: TGeoMatrix.cxx:575
Double_t E()
Definition: TMath.h:54
virtual Double_t DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact=1, Double_t step=0, Double_t *safe=0) const
Compute distance from a given point outside to the shape.
virtual void ComputeBBox(Double_t &dx, Double_t &dy, Double_t &dz, Double_t *origin)
Compute bounding box corresponding to a intersection of two shapes.
void CreateThreadData(Int_t nthreads)
Create thread data for n threads max.
Generic 3D primitive description class.
Definition: TBuffer3D.h:19
float xmax
Definition: THbookFile.cxx:93
virtual void SavePrimitive(std::ostream &out, Option_t *option="")
Save a primitive as a C++ statement(s) on output stream "out".
Bool_t ReplaceMatrix(TGeoMatrix *mat, TGeoMatrix *newmat)
Replace one of the matrices.
TGeoMatrix * fRightMat
Definition: TGeoBoolNode.h:50
static Int_t Lock()
Static method to lock the main thread mutex.
Definition: TThread.cxx:758
Double_t * fPoints
number of points on the mesh
Definition: TGeoBoolNode.h:52
virtual Double_t DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact=1, Double_t step=TGeoShape::Big(), Double_t *safe=0) const =0
TObjArray * GetListOfMatrices() const
Definition: TGeoManager.h:460
virtual void SavePrimitive(std::ostream &out, Option_t *option="")
Save a primitive as a C++ statement(s) on output stream "out".
virtual void LocalToMaster(const Double_t *local, Double_t *master) const
convert a point by multiplying its column vector (x, y, z, 1) to matrix inverse
Definition: TGeoMatrix.cxx:389
virtual Bool_t IsNullBox() const
Definition: TGeoBBox.h:79
virtual Double_t DistFromInside(const Double_t *point, const Double_t *dir, Int_t iact=1, Double_t step=TGeoShape::Big(), Double_t *safe=0) const =0
static Int_t UnLock()
Static method to unlock the main thread mutex.
Definition: TThread.cxx:774
ThreadData_t & GetThreadData() const
virtual ~TGeoIntersection()
Destructor — deletion of components handled by TGeoManager class.
#define ClassImp(name)
Definition: Rtypes.h:279
R__EXTERN TGeoManager * gGeoManager
Definition: TGeoManager.h:554
virtual void MasterToLocal(const Double_t *master, Double_t *local) const
convert a point by multiplying its column vector (x, y, z, 1) to matrix
Definition: TGeoMatrix.cxx:456
double Double_t
Definition: RtypesCore.h:55
Bool_t TestShapeBit(UInt_t f) const
Definition: TGeoShape.h:165
virtual void Paint(Option_t *option)
Paint method.
virtual TGeoBoolNode * MakeClone() const
Make a clone of this. Pointers are preserved.
virtual void Sizeof3D() const
Register size of this 3D object.
virtual void AddCompositeOp(UInt_t operation)=0
virtual void ComputeBBox()=0
static Double_t Big()
Definition: TGeoShape.h:90
static TGeoMatrix * GetTransform()
Returns current transformation matrix that applies to shape.
Definition: TGeoShape.cxx:538
R__EXTERN TGeoIdentity * gGeoIdentity
Definition: TGeoMatrix.h:464
static Int_t ThreadId()
Translates the current thread id to an ordinal number.
Base class for Boolean operations between two shapes.
Definition: TGeoBoolNode.h:24
Short_t Max(Short_t a, Short_t b)
Definition: TMathBase.h:202
void ClearThreadData() const
#define gPad
Definition: TVirtualPad.h:289
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition: TObject.cxx:953
const Bool_t kTRUE
Definition: Rtypes.h:91
double norm(double *x, double *p)
Definition: unuranDistr.cxx:40
virtual void ComputeBBox(Double_t &dx, Double_t &dy, Double_t &dz, Double_t *origin)
Compute bounding box corresponding to a union of two shapes.
virtual Int_t DistanceToPrimitive(Int_t px, Int_t py)
Compute minimum distance to shape vertices.
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:911
virtual void Paint(Option_t *option)
Paint method.
const char * Data() const
Definition: TString.h:349
virtual void SavePrimitive(std::ostream &out, Option_t *option="")
Save a primitive as a C++ statement(s) on output stream "out".
Definition: TObject.cxx:709