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