47 ClassImp(TGeoBoolNode);
52 TGeoBoolNode::ThreadData_t::ThreadData_t() :
60 TGeoBoolNode::ThreadData_t::~ThreadData_t()
66 TGeoBoolNode::ThreadData_t& TGeoBoolNode::GetThreadData()
const
68 Int_t tid = TGeoManager::ThreadId();
86 return *fThreadData[tid];
91 void TGeoBoolNode::ClearThreadData()
const
93 std::lock_guard<std::mutex> guard(fMutex);
94 std::vector<ThreadData_t*>::iterator i = fThreadData.begin();
95 while (i != fThreadData.end())
107 void TGeoBoolNode::CreateThreadData(Int_t nthreads)
109 std::lock_guard<std::mutex> guard(fMutex);
110 fThreadData.resize(nthreads);
111 fThreadSize = nthreads;
112 for (Int_t tid=0; tid<nthreads; tid++) {
113 if (fThreadData[tid] == 0) {
114 fThreadData[tid] =
new ThreadData_t;
118 if (fLeft) fLeft->CreateThreadData(nthreads);
119 if (fRight) fRight->CreateThreadData(nthreads);
125 void TGeoBoolNode::SetSelected(Int_t sel)
127 GetThreadData().fSelected = sel;
133 TGeoBoolNode::TGeoBoolNode()
148 TGeoBoolNode::TGeoBoolNode(
const char *expr1,
const char *expr2)
158 if (!MakeBranch(expr1, kTRUE)) {
161 if (!MakeBranch(expr2, kFALSE)) {
169 TGeoBoolNode::TGeoBoolNode(TGeoShape *left, TGeoShape *right, TGeoMatrix *lmat, TGeoMatrix *rmat)
178 if (!fLeftMat) fLeftMat = gGeoIdentity;
179 else fLeftMat->RegisterYourself();
181 if (!fRightMat) fRightMat = gGeoIdentity;
182 else fRightMat->RegisterYourself();
184 Error(
"ctor",
"left shape is NULL");
188 Error(
"ctor",
"right shape is NULL");
197 TGeoBoolNode::~TGeoBoolNode()
199 if (fPoints)
delete [] fPoints;
207 Bool_t TGeoBoolNode::MakeBranch(
const char *expr, Bool_t left)
209 TString sleft, sright, stransf;
210 Int_t boolop = TGeoManager::Parse(expr, sleft, sright, stransf);
212 Error(
"MakeBranch",
"invalid expression");
215 TGeoShape *shape = 0;
219 if (stransf.Length() == 0) {
222 mat = (TGeoMatrix*)gGeoManager->GetListOfMatrices()->FindObject(stransf.Data());
225 Error(
"MakeBranch",
"transformation %s not found", stransf.Data());
231 shape = (TGeoShape*)gGeoManager->GetListOfShapes()->FindObject(sleft.Data());
233 Error(
"MakeBranch",
"shape %s not found", sleft.Data());
242 shape =
new TGeoCompositeShape(newshape.Data());
249 shape =
new TGeoCompositeShape(newshape.Data());
256 shape =
new TGeoCompositeShape(newshape.Data());
259 if (boolop && (!shape || !shape->IsValid())) {
260 Error(
"MakeBranch",
"Shape %s not valid", newshape.Data());
261 if (shape)
delete shape;
277 void TGeoBoolNode::Paint(Option_t * option)
279 TVirtualViewer3D * viewer = gPad->GetViewer3D();
285 Bool_t localFrame = kFALSE;
287 TGeoHMatrix *glmat = (TGeoHMatrix*)TGeoShape::GetTransform();
296 glmat->Multiply(fLeftMat);
298 if (TGeoCompositeShape *left = dynamic_cast<TGeoCompositeShape *>(fLeft)) left->PaintComposite(option);
300 const TBuffer3D & leftBuffer = fLeft->GetBuffer3D(TBuffer3D::kAll, localFrame);
301 viewer->AddObject(leftBuffer);
306 glmat->Multiply(fRightMat);
308 if (TGeoCompositeShape *right = dynamic_cast<TGeoCompositeShape *>(fRight)) right->PaintComposite(option);
310 const TBuffer3D & rightBuffer = fRight->GetBuffer3D(TBuffer3D::kAll, localFrame);
311 viewer->AddObject(rightBuffer);
320 void TGeoBoolNode::RegisterMatrices()
322 if (!fLeftMat->IsIdentity()) fLeftMat->RegisterYourself();
323 if (!fRightMat->IsIdentity()) fRightMat->RegisterYourself();
324 if (fLeft->IsComposite()) ((TGeoCompositeShape*)fLeft)->GetBoolNode()->RegisterMatrices();
325 if (fRight->IsComposite()) ((TGeoCompositeShape*)fRight)->GetBoolNode()->RegisterMatrices();
332 Bool_t TGeoBoolNode::ReplaceMatrix(TGeoMatrix *mat, TGeoMatrix *newmat)
334 if (mat==gGeoIdentity || newmat==gGeoIdentity) {
335 Error(
"ReplaceMatrix",
"Matrices should not be gGeoIdentity. Use default matrix constructor to represent identities.");
338 if (!mat || !newmat) {
339 Error(
"ReplaceMatrix",
"Matrices should not be null pointers.");
342 Bool_t replaced = kFALSE;
343 if (fLeftMat == mat) {
347 if (fRightMat == mat) {
357 void TGeoBoolNode::SavePrimitive(std::ostream &out, Option_t *option )
359 fLeft->SavePrimitive(out,option);
360 fRight->SavePrimitive(out,option);
361 if (!fLeftMat->IsIdentity()) {
362 fLeftMat->RegisterYourself();
363 fLeftMat->SavePrimitive(out,option);
365 if (!fRightMat->IsIdentity()) {
366 fRightMat->RegisterYourself();
367 fRightMat->SavePrimitive(out,option);
374 void TGeoBoolNode::SetPoints(Double_t *points)
const
376 TGeoBoolNode *bn = (TGeoBoolNode*)
this;
377 Int_t npoints = bn->GetNpoints();
378 memcpy(points, fPoints, 3*npoints*
sizeof(Double_t));
384 void TGeoBoolNode::SetPoints(Float_t *points)
const
386 TGeoBoolNode *bn = (TGeoBoolNode*)
this;
387 Int_t npoints = bn->GetNpoints();
388 for (Int_t i=0; i<3*npoints; i++) points[i] = fPoints[i];
394 void TGeoBoolNode::Sizeof3D()
const
405 TGeoBoolNode *TGeoUnion::MakeClone()
const
407 return new TGeoUnion(fLeft, fRight, fLeftMat, fRightMat);
413 void TGeoUnion::Paint(Option_t *option)
415 TVirtualViewer3D *viewer = gPad->GetViewer3D();
418 Error(
"Paint",
"gPad->GetViewer3D() returned 0, cannot work with composite!\n");
422 viewer->AddCompositeOp(TBuffer3D::kCSUnion);
424 TGeoBoolNode::Paint(option);
430 TGeoUnion::TGeoUnion()
437 TGeoUnion::TGeoUnion(
const char *expr1,
const char *expr2)
438 :TGeoBoolNode(expr1, expr2)
445 TGeoUnion::TGeoUnion(TGeoShape *left, TGeoShape *right, TGeoMatrix *lmat, TGeoMatrix *rmat)
446 :TGeoBoolNode(left,right,lmat,rmat)
448 if (left->TestShapeBit(TGeoShape::kGeoHalfSpace) || right->TestShapeBit(TGeoShape::kGeoHalfSpace)) {
449 Fatal(
"TGeoUnion",
"Unions with a half-space (%s + %s) not allowed", left->GetName(), right->GetName());
457 TGeoUnion::~TGeoUnion()
464 void TGeoUnion::ComputeBBox(Double_t &dx, Double_t &dy, Double_t &dz, Double_t *origin)
466 if (((TGeoBBox*)fLeft)->IsNullBox()) fLeft->ComputeBBox();
467 if (((TGeoBBox*)fRight)->IsNullBox()) fRight->ComputeBBox();
471 Double_t xmin, xmax, ymin, ymax, zmin, zmax;
472 xmin = ymin = zmin = TGeoShape::Big();
473 xmax = ymax = zmax = -TGeoShape::Big();
474 ((TGeoBBox*)fLeft)->SetBoxPoints(&vert[0]);
475 ((TGeoBBox*)fRight)->SetBoxPoints(&vert[24]);
476 for (i=0; i<8; i++) {
477 fLeftMat->LocalToMaster(&vert[3*i], &pt[0]);
478 if (pt[0]<xmin) xmin=pt[0];
479 if (pt[0]>xmax) xmax=pt[0];
480 if (pt[1]<ymin) ymin=pt[1];
481 if (pt[1]>ymax) ymax=pt[1];
482 if (pt[2]<zmin) zmin=pt[2];
483 if (pt[2]>zmax) zmax=pt[2];
485 for (i=8; i<16; i++) {
486 fRightMat->LocalToMaster(&vert[3*i], &pt[0]);
487 if (pt[0]<xmin) xmin=pt[0];
488 if (pt[0]>xmax) xmax=pt[0];
489 if (pt[1]<ymin) ymin=pt[1];
490 if (pt[1]>ymax) ymax=pt[1];
491 if (pt[2]<zmin) zmin=pt[2];
492 if (pt[2]>zmax) zmax=pt[2];
494 dx = 0.5*(xmax-xmin);
495 origin[0] = 0.5*(xmin+xmax);
496 dy = 0.5*(ymax-ymin);
497 origin[1] = 0.5*(ymin+ymax);
498 dz = 0.5*(zmax-zmin);
499 origin[2] = 0.5*(zmin+zmax);
505 Bool_t TGeoUnion::Contains(
const Double_t *point)
const
508 fLeftMat->MasterToLocal(point, &local[0]);
509 Bool_t inside = fLeft->Contains(&local[0]);
510 if (inside)
return kTRUE;
511 fRightMat->MasterToLocal(point, &local[0]);
512 inside = fRight->Contains(&local[0]);
519 void TGeoUnion::ComputeNormal(
const Double_t *point,
const Double_t *dir, Double_t *norm)
521 ThreadData_t& td = GetThreadData();
522 norm[0] = norm[1] = 0.;
525 Double_t ldir[3], lnorm[3];
526 if (td.fSelected == 1) {
527 fLeftMat->MasterToLocal(point, local);
528 fLeftMat->MasterToLocalVect(dir, ldir);
529 fLeft->ComputeNormal(local,ldir,lnorm);
530 fLeftMat->LocalToMasterVect(lnorm, norm);
533 if (td.fSelected == 2) {
534 fRightMat->MasterToLocal(point, local);
535 fRightMat->MasterToLocalVect(dir, ldir);
536 fRight->ComputeNormal(local,ldir,lnorm);
537 fRightMat->LocalToMasterVect(lnorm, norm);
540 fLeftMat->MasterToLocal(point, local);
541 if (fLeft->Contains(local)) {
542 fLeftMat->MasterToLocalVect(dir, ldir);
543 fLeft->ComputeNormal(local,ldir,lnorm);
544 fLeftMat->LocalToMasterVect(lnorm, norm);
547 fRightMat->MasterToLocal(point, local);
548 if (fRight->Contains(local)) {
549 fRightMat->MasterToLocalVect(dir, ldir);
550 fRight->ComputeNormal(local,ldir,lnorm);
551 fRightMat->LocalToMasterVect(lnorm, norm);
555 local[0] = point[0] + 1E-5*dir[0];
556 local[1] = point[1] + 1E-5*dir[1];
557 local[2] = point[2] + 1E-5*dir[2];
559 if (!Contains(local)) {
560 local[0] = point[0] - 1E-5*dir[0];
561 local[1] = point[1] - 1E-5*dir[1];
562 local[2] = point[2] - 1E-5*dir[2];
563 if (!Contains(local))
return;
565 ComputeNormal(local,dir,norm);
571 Int_t TGeoUnion::DistanceToPrimitive(Int_t , Int_t )
579 Double_t TGeoUnion::DistFromInside(
const Double_t *point,
const Double_t *dir, Int_t iact,
580 Double_t step, Double_t *safe)
const
582 if (iact<3 && safe) {
584 *safe = Safety(point,kTRUE);
585 if (iact==0)
return TGeoShape::Big();
586 if (iact==1 && step<*safe)
return TGeoShape::Big();
589 Double_t local[3], local1[3], master[3], ldir[3], rdir[3], pushed[3];
590 memcpy(master, point, 3*
sizeof(Double_t));
592 TGeoBoolNode *node = (TGeoBoolNode*)
this;
593 Double_t d1=0., d2=0., snxt=0., eps=0.;
594 fLeftMat->MasterToLocalVect(dir, ldir);
595 fRightMat->MasterToLocalVect(dir, rdir);
596 fLeftMat->MasterToLocal(point, local);
597 Bool_t inside1 = fLeft->Contains(local);
598 if (inside1) d1 = fLeft->DistFromInside(local, ldir, 3);
599 else memcpy(local1, local, 3*
sizeof(Double_t));
600 fRightMat->MasterToLocal(point, local);
601 Bool_t inside2 = fRight->Contains(local);
602 if (inside2) d2 = fRight->DistFromInside(local, rdir, 3);
603 if (!(inside1 | inside2)) {
605 d1 = fLeft->DistFromOutside(local1, ldir, 3);
607 eps = d1+TGeoShape::Tolerance();
608 for (i=0; i<3; i++) local1[i] += eps*ldir[i];
610 d1 = fLeft->DistFromInside(local1, ldir, 3);
613 d2 = fRight->DistFromOutside(local, rdir, 3);
615 eps = d2+TGeoShape::Tolerance();
616 for (i=0; i<3; i++) local[i] += eps*rdir[i];
618 d2 = fRight->DistFromInside(local, rdir, 3);
623 while (inside1 || inside2) {
624 if (inside1 && inside2) {
627 node->SetSelected(1);
630 for (i=0; i<3; i++) master[i] += d1*dir[i];
632 fRightMat->MasterToLocal(master, local);
633 inside2 = fRight->Contains(local);
634 if (!inside2)
return snxt;
635 d2 = fRight->DistFromInside(local, rdir, 3);
636 if (d2 < TGeoShape::Tolerance())
return snxt;
639 node->SetSelected(2);
642 for (i=0; i<3; i++) master[i] += d2*dir[i];
644 fLeftMat->MasterToLocal(master, local);
645 inside1 = fLeft->Contains(local);
646 if (!inside1)
return snxt;
647 d1 = fLeft->DistFromInside(local, ldir, 3);
648 if (d1 < TGeoShape::Tolerance())
return snxt;
653 node->SetSelected(1);
656 for (i=0; i<3; i++) {
657 master[i] += d1*dir[i];
658 pushed[i] = master[i]+(1.+d1)*TGeoShape::Tolerance()*dir[i];
661 fRightMat->MasterToLocal(pushed, local);
662 inside2 = fRight->Contains(local);
663 if (!inside2)
return snxt;
664 d2 = fRight->DistFromInside(local, rdir, 3);
665 if (d2 < TGeoShape::Tolerance())
return snxt;
666 d2 += (1.+d1)*TGeoShape::Tolerance();
670 node->SetSelected(2);
673 for (i=0; i<3; i++) {
674 master[i] += d2*dir[i];
675 pushed[i] = master[i]+(1.+d2)*TGeoShape::Tolerance()*dir[i];
678 fLeftMat->MasterToLocal(pushed, local);
679 inside1 = fLeft->Contains(local);
680 if (!inside1)
return snxt;
681 d1 = fLeft->DistFromInside(local, ldir, 3);
682 if (d1 < TGeoShape::Tolerance())
return snxt;
683 d1 += (1.+d2)*TGeoShape::Tolerance();
692 Double_t TGeoUnion::DistFromOutside(
const Double_t *point,
const Double_t *dir, Int_t iact,
693 Double_t step, Double_t *safe)
const
695 if (iact<3 && safe) {
697 *safe = Safety(point,kFALSE);
698 if (iact==0)
return TGeoShape::Big();
699 if (iact==1 && step<*safe)
return TGeoShape::Big();
701 TGeoBoolNode *node = (TGeoBoolNode*)
this;
702 Double_t local[3], ldir[3], rdir[3];
703 Double_t d1, d2, snxt;
704 fLeftMat->MasterToLocal(point, &local[0]);
705 fLeftMat->MasterToLocalVect(dir, &ldir[0]);
706 fRightMat->MasterToLocalVect(dir, &rdir[0]);
707 d1 = fLeft->DistFromOutside(&local[0], &ldir[0], iact, step, safe);
708 fRightMat->MasterToLocal(point, &local[0]);
709 d2 = fRight->DistFromOutside(&local[0], &rdir[0], iact, step, safe);
712 node->SetSelected(1);
715 node->SetSelected(2);
723 Int_t TGeoUnion::GetNpoints()
727 Double_t tolerance = TGeoShape::Tolerance();
728 if (fNpoints)
return fNpoints;
730 Int_t nleft = fLeft->GetNmeshVertices();
731 Double_t *points1 =
new Double_t[3*nleft];
732 fLeft->SetPoints(points1);
734 Int_t nright = fRight->GetNmeshVertices();
735 Double_t *points2 =
new Double_t[3*nright];
736 fRight->SetPoints(points2);
737 Double_t *points =
new Double_t[3*(nleft+nright)];
738 for (Int_t i=0; i<nleft; i++) {
739 if (TMath::Abs(points1[3*i])<tolerance && TMath::Abs(points1[3*i+1])<tolerance)
continue;
740 fLeftMat->LocalToMaster(&points1[3*i], &points[3*itot]);
741 fRightMat->MasterToLocal(&points[3*itot], point);
742 if (!fRight->Contains(point)) itot++;
744 for (Int_t i=0; i<nright; i++) {
745 if (TMath::Abs(points2[3*i])<tolerance && TMath::Abs(points2[3*i+1])<tolerance)
continue;
746 fRightMat->LocalToMaster(&points2[3*i], &points[3*itot]);
747 fLeftMat->MasterToLocal(&points[3*itot], point);
748 if (!fLeft->Contains(point)) itot++;
751 fPoints =
new Double_t[3*fNpoints];
752 memcpy(fPoints, points, 3*fNpoints*
sizeof(Double_t));
762 Double_t TGeoUnion::Safety(
const Double_t *point, Bool_t in)
const
764 Double_t local1[3], local2[3];
765 fLeftMat->MasterToLocal(point,local1);
766 Bool_t in1 = fLeft->Contains(local1);
767 fRightMat->MasterToLocal(point,local2);
768 Bool_t in2 = fRight->Contains(local2);
769 Bool_t intrue = in1 | in2;
770 if (intrue^in)
return 0.0;
771 Double_t saf1 = fLeft->Safety(local1, in1);
772 Double_t saf2 = fRight->Safety(local2, in2);
773 if (in1 && in2)
return TMath::Min(saf1, saf2);
774 if (in1)
return saf1;
775 if (in2)
return saf2;
776 return TMath::Min(saf1,saf2);
782 void TGeoUnion::SavePrimitive(std::ostream &out, Option_t *option )
784 TGeoBoolNode::SavePrimitive(out,option);
785 out <<
" pBoolNode = new TGeoUnion(";
786 out << fLeft->GetPointerName() <<
",";
787 out << fRight->GetPointerName() <<
",";
788 if (!fLeftMat->IsIdentity()) out << fLeftMat->GetPointerName() <<
",";
790 if (!fRightMat->IsIdentity()) out << fRightMat->GetPointerName() <<
");" << std::endl;
791 else out <<
"0);" << std::endl;
797 void TGeoUnion::Sizeof3D()
const
799 TGeoBoolNode::Sizeof3D();
803 ClassImp(TGeoSubtraction);
808 TGeoBoolNode *TGeoSubtraction::MakeClone()
const
810 return new TGeoSubtraction(fLeft, fRight, fLeftMat, fRightMat);
816 void TGeoSubtraction::Paint(Option_t *option)
818 TVirtualViewer3D *viewer = gPad->GetViewer3D();
821 Error(
"Paint",
"gPad->GetViewer3D() returned 0, cannot work with composite!\n");
825 viewer->AddCompositeOp(TBuffer3D::kCSDifference);
827 TGeoBoolNode::Paint(option);
833 TGeoSubtraction::TGeoSubtraction()
840 TGeoSubtraction::TGeoSubtraction(
const char *expr1,
const char *expr2)
841 :TGeoBoolNode(expr1, expr2)
848 TGeoSubtraction::TGeoSubtraction(TGeoShape *left, TGeoShape *right, TGeoMatrix *lmat, TGeoMatrix *rmat)
849 :TGeoBoolNode(left,right,lmat,rmat)
851 if (left->TestShapeBit(TGeoShape::kGeoHalfSpace)) {
852 Fatal(
"TGeoSubstraction",
"Subtractions from a half-space (%s) not allowed", left->GetName());
860 TGeoSubtraction::~TGeoSubtraction()
867 void TGeoSubtraction::ComputeBBox(Double_t &dx, Double_t &dy, Double_t &dz, Double_t *origin)
869 TGeoBBox *box = (TGeoBBox*)fLeft;
870 if (box->IsNullBox()) fLeft->ComputeBBox();
874 Double_t xmin, xmax, ymin, ymax, zmin, zmax;
875 xmin = ymin = zmin = TGeoShape::Big();
876 xmax = ymax = zmax = -TGeoShape::Big();
877 box->SetBoxPoints(&vert[0]);
878 for (i=0; i<8; i++) {
879 fLeftMat->LocalToMaster(&vert[3*i], &pt[0]);
880 if (pt[0]<xmin) xmin=pt[0];
881 if (pt[0]>xmax) xmax=pt[0];
882 if (pt[1]<ymin) ymin=pt[1];
883 if (pt[1]>ymax) ymax=pt[1];
884 if (pt[2]<zmin) zmin=pt[2];
885 if (pt[2]>zmax) zmax=pt[2];
887 dx = 0.5*(xmax-xmin);
888 origin[0] = 0.5*(xmin+xmax);
889 dy = 0.5*(ymax-ymin);
890 origin[1] = 0.5*(ymin+ymax);
891 dz = 0.5*(zmax-zmin);
892 origin[2] = 0.5*(zmin+zmax);
898 void TGeoSubtraction::ComputeNormal(
const Double_t *point,
const Double_t *dir, Double_t *norm)
900 ThreadData_t& td = GetThreadData();
901 norm[0] = norm[1] = 0.;
903 Double_t local[3], ldir[3], lnorm[3];
904 if (td.fSelected == 1) {
905 fLeftMat->MasterToLocal(point, local);
906 fLeftMat->MasterToLocalVect(dir, ldir);
907 fLeft->ComputeNormal(local,ldir,lnorm);
908 fLeftMat->LocalToMasterVect(lnorm, norm);
911 if (td.fSelected == 2) {
912 fRightMat->MasterToLocal(point, local);
913 fRightMat->MasterToLocalVect(dir, ldir);
914 fRight->ComputeNormal(local,ldir,lnorm);
915 fRightMat->LocalToMasterVect(lnorm, norm);
918 fRightMat->MasterToLocal(point,local);
919 if (fRight->Contains(local)) {
920 fRightMat->MasterToLocalVect(dir,ldir);
921 fRight->ComputeNormal(local,ldir, lnorm);
922 fRightMat->LocalToMasterVect(lnorm,norm);
925 fLeftMat->MasterToLocal(point,local);
926 if (!fLeft->Contains(local)) {
927 fLeftMat->MasterToLocalVect(dir,ldir);
928 fLeft->ComputeNormal(local,ldir, lnorm);
929 fLeftMat->LocalToMasterVect(lnorm,norm);
933 local[0] = point[0]+1E-5*dir[0];
934 local[1] = point[1]+1E-5*dir[1];
935 local[2] = point[2]+1E-5*dir[2];
936 if (Contains(local)) {
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))
return;
942 ComputeNormal(local,dir,norm);
948 Bool_t TGeoSubtraction::Contains(
const Double_t *point)
const
951 fLeftMat->MasterToLocal(point, &local[0]);
952 Bool_t inside = fLeft->Contains(&local[0]);
953 if (!inside)
return kFALSE;
954 fRightMat->MasterToLocal(point, &local[0]);
955 inside = !fRight->Contains(&local[0]);
962 Int_t TGeoSubtraction::DistanceToPrimitive(Int_t , Int_t )
970 Double_t TGeoSubtraction::DistFromInside(
const Double_t *point,
const Double_t *dir, Int_t iact,
971 Double_t step, Double_t *safe)
const
973 if (iact<3 && safe) {
975 *safe = Safety(point,kTRUE);
976 if (iact==0)
return TGeoShape::Big();
977 if (iact==1 && step<*safe)
return TGeoShape::Big();
979 TGeoBoolNode *node = (TGeoBoolNode*)
this;
980 Double_t local[3], ldir[3], rdir[3];
981 Double_t d1, d2, snxt=0.;
982 fLeftMat->MasterToLocal(point, &local[0]);
983 fLeftMat->MasterToLocalVect(dir, &ldir[0]);
984 fRightMat->MasterToLocalVect(dir, &rdir[0]);
985 d1 = fLeft->DistFromInside(&local[0], &ldir[0], iact, step, safe);
986 fRightMat->MasterToLocal(point, &local[0]);
987 d2 = fRight->DistFromOutside(&local[0], &rdir[0], iact, step, safe);
990 node->SetSelected(1);
993 node->SetSelected(2);
1001 Double_t TGeoSubtraction::DistFromOutside(
const Double_t *point,
const Double_t *dir, Int_t iact,
1002 Double_t step, Double_t *safe)
const
1004 if (iact<3 && safe) {
1006 *safe = Safety(point,kFALSE);
1007 if (iact==0)
return TGeoShape::Big();
1008 if (iact==1 && step<*safe)
return TGeoShape::Big();
1010 TGeoBoolNode *node = (TGeoBoolNode*)
this;
1011 Double_t local[3], master[3], ldir[3], rdir[3];
1012 memcpy(&master[0], point, 3*
sizeof(Double_t));
1014 Double_t d1, d2, snxt=0.;
1015 fRightMat->MasterToLocal(point, &local[0]);
1016 fLeftMat->MasterToLocalVect(dir, &ldir[0]);
1017 fRightMat->MasterToLocalVect(dir, &rdir[0]);
1019 Bool_t inside = fRight->Contains(&local[0]);
1020 Double_t epsil = 0.;
1024 node->SetSelected(2);
1025 d1 = fRight->DistFromInside(&local[0], &rdir[0], iact, step, safe);
1027 for (i=0; i<3; i++) master[i] += (d1+1E-8)*dir[i];
1030 fLeftMat->MasterToLocal(&master[0], &local[0]);
1031 if (fLeft->Contains(&local[0]))
return snxt;
1034 node->SetSelected(1);
1035 fLeftMat->MasterToLocal(&master[0], &local[0]);
1036 d2 = fLeft->DistFromOutside(&local[0], &ldir[0], iact, step, safe);
1037 if (d2>1E20)
return TGeoShape::Big();
1039 fRightMat->MasterToLocal(&master[0], &local[0]);
1040 d1 = fRight->DistFromOutside(&local[0], &rdir[0], iact, step, safe);
1041 if (d2<d1-TGeoShape::Tolerance()) {
1047 for (i=0; i<3; i++) master[i] += (d1+1E-8)*dir[i];
1050 fRightMat->MasterToLocal(&master[0], &local[0]);
1058 Int_t TGeoSubtraction::GetNpoints()
1062 Double_t tolerance = TGeoShape::Tolerance();
1063 if (fNpoints)
return fNpoints;
1064 Int_t nleft = fLeft->GetNmeshVertices();
1065 Int_t nright = fRight->GetNmeshVertices();
1066 Double_t *points =
new Double_t[3*(nleft+nright)];
1067 Double_t *points1 =
new Double_t[3*nleft];
1068 fLeft->SetPoints(points1);
1069 for (Int_t i=0; i<nleft; i++) {
1070 if (TMath::Abs(points1[3*i])<tolerance && TMath::Abs(points1[3*i+1])<tolerance)
continue;
1071 fLeftMat->LocalToMaster(&points1[3*i], &points[3*itot]);
1072 fRightMat->MasterToLocal(&points[3*itot], point);
1073 if (!fRight->Contains(point)) itot++;
1075 Double_t *points2 =
new Double_t[3*nright];
1076 fRight->SetPoints(points2);
1077 for (Int_t i=0; i<nright; i++) {
1078 if (TMath::Abs(points2[3*i])<tolerance && TMath::Abs(points2[3*i+1])<tolerance)
continue;
1079 fRightMat->LocalToMaster(&points2[3*i], &points[3*itot]);
1080 fLeftMat->MasterToLocal(&points[3*itot], point);
1081 if (fLeft->Contains(point)) itot++;
1084 fPoints =
new Double_t[3*fNpoints];
1085 memcpy(fPoints, points, 3*fNpoints*
sizeof(Double_t));
1095 Double_t TGeoSubtraction::Safety(
const Double_t *point, Bool_t in)
const
1097 Double_t local1[3], local2[3];
1098 fLeftMat->MasterToLocal(point,local1);
1099 Bool_t in1 = fLeft->Contains(local1);
1100 fRightMat->MasterToLocal(point,local2);
1101 Bool_t in2 = fRight->Contains(local2);
1102 Bool_t intrue = in1 && (!in2);
1103 if (in^intrue)
return 0.0;
1104 Double_t saf1 = fLeft->Safety(local1, in1);
1105 Double_t saf2 = fRight->Safety(local2, in2);
1106 if (in1 && in2)
return saf2;
1107 if (in1)
return TMath::Min(saf1,saf2);
1108 if (in2)
return TMath::Max(saf1,saf2);
1115 void TGeoSubtraction::SavePrimitive(std::ostream &out, Option_t *option )
1117 TGeoBoolNode::SavePrimitive(out,option);
1118 out <<
" pBoolNode = new TGeoSubtraction(";
1119 out << fLeft->GetPointerName() <<
",";
1120 out << fRight->GetPointerName() <<
",";
1121 if (!fLeftMat->IsIdentity()) out << fLeftMat->GetPointerName() <<
",";
1123 if (!fRightMat->IsIdentity()) out << fRightMat->GetPointerName() <<
");" << std::endl;
1124 else out <<
"0);" << std::endl;
1130 void TGeoSubtraction::Sizeof3D()
const
1132 TGeoBoolNode::Sizeof3D();
1135 ClassImp(TGeoIntersection);
1140 TGeoBoolNode *TGeoIntersection::MakeClone()
const
1142 return new TGeoIntersection(fLeft, fRight, fLeftMat, fRightMat);
1148 void TGeoIntersection::Paint(Option_t *option)
1150 TVirtualViewer3D *viewer = gPad->GetViewer3D();
1153 Error(
"Paint",
"gPad->GetViewer3D() returned 0, cannot work with composite!\n");
1157 viewer->AddCompositeOp(TBuffer3D::kCSIntersection);
1159 TGeoBoolNode::Paint(option);
1165 TGeoIntersection::TGeoIntersection()
1172 TGeoIntersection::TGeoIntersection(
const char *expr1,
const char *expr2)
1173 :TGeoBoolNode(expr1, expr2)
1180 TGeoIntersection::TGeoIntersection(TGeoShape *left, TGeoShape *right, TGeoMatrix *lmat, TGeoMatrix *rmat)
1181 :TGeoBoolNode(left,right,lmat,rmat)
1183 Bool_t hs1 = (fLeft->TestShapeBit(TGeoShape::kGeoHalfSpace))?kTRUE:kFALSE;
1184 Bool_t hs2 = (fRight->TestShapeBit(TGeoShape::kGeoHalfSpace))?kTRUE:kFALSE;
1185 if (hs1 && hs2) Fatal(
"ctor",
"cannot intersect two half-spaces: %s * %s", left->GetName(), right->GetName());
1192 TGeoIntersection::~TGeoIntersection()
1199 void TGeoIntersection::ComputeBBox(Double_t &dx, Double_t &dy, Double_t &dz, Double_t *origin)
1201 Bool_t hs1 = (fLeft->TestShapeBit(TGeoShape::kGeoHalfSpace))?kTRUE:kFALSE;
1202 Bool_t hs2 = (fRight->TestShapeBit(TGeoShape::kGeoHalfSpace))?kTRUE:kFALSE;
1206 Double_t xmin1, xmax1, ymin1, ymax1, zmin1, zmax1;
1207 Double_t xmin2, xmax2, ymin2, ymax2, zmin2, zmax2;
1208 xmin1 = ymin1 = zmin1 = xmin2 = ymin2 = zmin2 = TGeoShape::Big();
1209 xmax1 = ymax1 = zmax1 = xmax2 = ymax2 = zmax2 = -TGeoShape::Big();
1211 if (((TGeoBBox*)fLeft)->IsNullBox()) fLeft->ComputeBBox();
1212 ((TGeoBBox*)fLeft)->SetBoxPoints(&vert[0]);
1213 for (i=0; i<8; i++) {
1214 fLeftMat->LocalToMaster(&vert[3*i], &pt[0]);
1215 if (pt[0]<xmin1) xmin1=pt[0];
1216 if (pt[0]>xmax1) xmax1=pt[0];
1217 if (pt[1]<ymin1) ymin1=pt[1];
1218 if (pt[1]>ymax1) ymax1=pt[1];
1219 if (pt[2]<zmin1) zmin1=pt[2];
1220 if (pt[2]>zmax1) zmax1=pt[2];
1224 if (((TGeoBBox*)fRight)->IsNullBox()) fRight->ComputeBBox();
1225 ((TGeoBBox*)fRight)->SetBoxPoints(&vert[24]);
1226 for (i=8; i<16; i++) {
1227 fRightMat->LocalToMaster(&vert[3*i], &pt[0]);
1228 if (pt[0]<xmin2) xmin2=pt[0];
1229 if (pt[0]>xmax2) xmax2=pt[0];
1230 if (pt[1]<ymin2) ymin2=pt[1];
1231 if (pt[1]>ymax2) ymax2=pt[1];
1232 if (pt[2]<zmin2) zmin2=pt[2];
1233 if (pt[2]>zmax2) zmax2=pt[2];
1237 dx = 0.5*(xmax2-xmin2);
1238 origin[0] = 0.5*(xmax2+xmin2);
1239 dy = 0.5*(ymax2-ymin2);
1240 origin[1] = 0.5*(ymax2+ymin2);
1241 dz = 0.5*(zmax2-zmin2);
1242 origin[2] = 0.5*(zmax2+zmin2);
1246 dx = 0.5*(xmax1-xmin1);
1247 origin[0] = 0.5*(xmax1+xmin1);
1248 dy = 0.5*(ymax1-ymin1);
1249 origin[1] = 0.5*(ymax1+ymin1);
1250 dz = 0.5*(zmax1-zmin1);
1251 origin[2] = 0.5*(zmax1+zmin1);
1260 TMath::Sort(4, &sort[0], &isort[0], kFALSE);
1262 Warning(
"ComputeBBox",
"shapes %s and %s do not intersect", fLeft->GetName(), fRight->GetName());
1264 memset(origin, 0, 3*
sizeof(Double_t));
1267 dx = 0.5*(sort[isort[2]]-sort[isort[1]]);
1268 origin[0] = 0.5*(sort[isort[1]]+sort[isort[2]]);
1273 TMath::Sort(4, &sort[0], &isort[0], kFALSE);
1275 Warning(
"ComputeBBox",
"shapes %s and %s do not intersect", fLeft->GetName(), fRight->GetName());
1277 memset(origin, 0, 3*
sizeof(Double_t));
1280 dy = 0.5*(sort[isort[2]]-sort[isort[1]]);
1281 origin[1] = 0.5*(sort[isort[1]]+sort[isort[2]]);
1286 TMath::Sort(4, &sort[0], &isort[0], kFALSE);
1288 Warning(
"ComputeBBox",
"shapes %s and %s do not intersect", fLeft->GetName(), fRight->GetName());
1290 memset(origin, 0, 3*
sizeof(Double_t));
1293 dz = 0.5*(sort[isort[2]]-sort[isort[1]]);
1294 origin[2] = 0.5*(sort[isort[1]]+sort[isort[2]]);
1300 void TGeoIntersection::ComputeNormal(
const Double_t *point,
const Double_t *dir, Double_t *norm)
1302 ThreadData_t& td = GetThreadData();
1303 Double_t local[3], ldir[3], lnorm[3];
1304 norm[0] = norm[1] = 0.;
1306 if (td.fSelected == 1) {
1307 fLeftMat->MasterToLocal(point, local);
1308 fLeftMat->MasterToLocalVect(dir, ldir);
1309 fLeft->ComputeNormal(local,ldir,lnorm);
1310 fLeftMat->LocalToMasterVect(lnorm, norm);
1313 if (td.fSelected == 2) {
1314 fRightMat->MasterToLocal(point, local);
1315 fRightMat->MasterToLocalVect(dir, ldir);
1316 fRight->ComputeNormal(local,ldir,lnorm);
1317 fRightMat->LocalToMasterVect(lnorm, norm);
1320 fLeftMat->MasterToLocal(point,local);
1321 if (!fLeft->Contains(local)) {
1322 fLeftMat->MasterToLocalVect(dir,ldir);
1323 fLeft->ComputeNormal(local,ldir,lnorm);
1324 fLeftMat->LocalToMasterVect(lnorm,norm);
1327 fRightMat->MasterToLocal(point,local);
1328 if (!fRight->Contains(local)) {
1329 fRightMat->MasterToLocalVect(dir,ldir);
1330 fRight->ComputeNormal(local,ldir,lnorm);
1331 fRightMat->LocalToMasterVect(lnorm,norm);
1335 local[0] = point[0] + 1E-5*dir[0];
1336 local[1] = point[1] + 1E-5*dir[1];
1337 local[2] = point[2] + 1E-5*dir[2];
1338 if (Contains(local)) {
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))
return;
1344 ComputeNormal(local,dir,norm);
1350 Bool_t TGeoIntersection::Contains(
const Double_t *point)
const
1353 fLeftMat->MasterToLocal(point, &local[0]);
1354 Bool_t inside = fLeft->Contains(&local[0]);
1355 if (!inside)
return kFALSE;
1356 fRightMat->MasterToLocal(point, &local[0]);
1357 inside = fRight->Contains(&local[0]);
1364 Int_t TGeoIntersection::DistanceToPrimitive(Int_t , Int_t )
1372 Double_t TGeoIntersection::DistFromInside(
const Double_t *point,
const Double_t *dir, Int_t iact,
1373 Double_t step, Double_t *safe)
const
1375 if (iact<3 && safe) {
1377 *safe = Safety(point,kTRUE);
1378 if (iact==0)
return TGeoShape::Big();
1379 if (iact==1 && step<*safe)
return TGeoShape::Big();
1381 TGeoBoolNode *node = (TGeoBoolNode*)
this;
1382 Double_t local[3], ldir[3], rdir[3];
1383 Double_t d1, d2, snxt=0.;
1384 fLeftMat->MasterToLocal(point, &local[0]);
1385 fLeftMat->MasterToLocalVect(dir, &ldir[0]);
1386 fRightMat->MasterToLocalVect(dir, &rdir[0]);
1387 d1 = fLeft->DistFromInside(&local[0], &ldir[0], iact, step, safe);
1388 fRightMat->MasterToLocal(point, &local[0]);
1389 d2 = fRight->DistFromInside(&local[0], &rdir[0], iact, step, safe);
1392 node->SetSelected(1);
1395 node->SetSelected(2);
1403 Double_t TGeoIntersection::DistFromOutside(
const Double_t *point,
const Double_t *dir, Int_t iact,
1404 Double_t step, Double_t *safe)
const
1406 Double_t tol = TGeoShape::Tolerance();
1407 if (iact<3 && safe) {
1409 *safe = Safety(point,kFALSE);
1410 if (iact==0)
return TGeoShape::Big();
1411 if (iact==1 && step<*safe)
return TGeoShape::Big();
1413 TGeoBoolNode *node = (TGeoBoolNode*)
this;
1414 Double_t lpt[3], rpt[3], master[3], ldir[3], rdir[3];
1415 memcpy(master, point, 3*
sizeof(Double_t));
1419 fLeftMat->MasterToLocal(point, lpt);
1420 fRightMat->MasterToLocal(point, rpt);
1421 fLeftMat->MasterToLocalVect(dir, ldir);
1422 fRightMat->MasterToLocalVect(dir, rdir);
1423 Bool_t inleft = fLeft->Contains(lpt);
1424 Bool_t inright = fRight->Contains(rpt);
1425 node->SetSelected(0);
1426 Double_t snext = 0.0;
1427 if (inleft && inright) {
1430 d1 = fLeft->DistFromInside(lpt,ldir,3);
1431 d2 = fRight->DistFromInside(rpt,rdir,3);
1432 if (d1<1.E-3) inleft = kFALSE;
1433 if (d2<1.E-3) inright = kFALSE;
1434 if (inleft && inright)
return snext;
1440 d1 = fLeft->DistFromOutside(lpt,ldir,3);
1441 d1 = TMath::Max(d1,tol);
1442 if (d1>1E20)
return TGeoShape::Big();
1445 d2 = fRight->DistFromOutside(rpt,rdir,3);
1446 d2 = TMath::Max(d2,tol);
1447 if (d2>1E20)
return TGeoShape::Big();
1453 node->SetSelected(1);
1455 for (i=0; i<3; i++) master[i] += d1*dir[i];
1456 fRightMat->MasterToLocal(master,rpt);
1458 for (i=0; i<3; i++) rpt[i] += tol*rdir[i];
1460 inright = fRight->Contains(rpt);
1461 if (inright)
return snext;
1466 node->SetSelected(2);
1468 for (i=0; i<3; i++) master[i] += d2*dir[i];
1469 fLeftMat->MasterToLocal(master,lpt);
1471 for (i=0; i<3; i++) lpt[i] += tol*ldir[i];
1473 inleft = fLeft->Contains(lpt);
1474 if (inleft)
return snext;
1484 Int_t TGeoIntersection::GetNpoints()
1488 Double_t tolerance = TGeoShape::Tolerance();
1489 if (fNpoints)
return fNpoints;
1490 Int_t nleft = fLeft->GetNmeshVertices();
1491 Int_t nright = fRight->GetNmeshVertices();
1492 Double_t *points =
new Double_t[3*(nleft+nright)];
1493 Double_t *points1 =
new Double_t[3*nleft];
1494 fLeft->SetPoints(points1);
1495 for (Int_t i=0; i<nleft; i++) {
1496 if (TMath::Abs(points1[3*i])<tolerance && TMath::Abs(points1[3*i+1])<tolerance)
continue;
1497 fLeftMat->LocalToMaster(&points1[3*i], &points[3*itot]);
1498 fRightMat->MasterToLocal(&points[3*itot], point);
1499 if (fRight->Contains(point)) itot++;
1501 Double_t *points2 =
new Double_t[3*nright];
1502 fRight->SetPoints(points2);
1503 for (Int_t i=0; i<nright; i++) {
1504 if (TMath::Abs(points2[3*i])<tolerance && TMath::Abs(points2[3*i+1])<tolerance)
continue;
1505 fRightMat->LocalToMaster(&points2[3*i], &points[3*itot]);
1506 fLeftMat->MasterToLocal(&points[3*itot], point);
1507 if (fLeft->Contains(point)) itot++;
1510 fPoints =
new Double_t[3*fNpoints];
1511 memcpy(fPoints, points, 3*fNpoints*
sizeof(Double_t));
1521 Double_t TGeoIntersection::Safety(
const Double_t *point, Bool_t in)
const
1523 Double_t local1[3], local2[3];
1524 fLeftMat->MasterToLocal(point,local1);
1525 Bool_t in1 = fLeft->Contains(local1);
1526 fRightMat->MasterToLocal(point,local2);
1527 Bool_t in2 = fRight->Contains(local2);
1528 Bool_t intrue = in1 & in2;
1529 if (in^intrue)
return 0.0;
1530 Double_t saf1 = fLeft->Safety(local1, in1);
1531 Double_t saf2 = fRight->Safety(local2, in2);
1532 if (in1 && in2)
return TMath::Min(saf1, saf2);
1533 if (in1)
return saf2;
1534 if (in2)
return saf1;
1535 return TMath::Max(saf1,saf2);
1541 void TGeoIntersection::SavePrimitive(std::ostream &out, Option_t *option )
1543 TGeoBoolNode::SavePrimitive(out,option);
1544 out <<
" pBoolNode = new TGeoIntersection(";
1545 out << fLeft->GetPointerName() <<
",";
1546 out << fRight->GetPointerName() <<
",";
1547 if (!fLeftMat->IsIdentity()) out << fLeftMat->GetPointerName() <<
",";
1549 if (!fRightMat->IsIdentity()) out << fRightMat->GetPointerName() <<
");" << std::endl;
1550 else out <<
"0);" << std::endl;
1556 void TGeoIntersection::Sizeof3D()
const
1558 TGeoBoolNode::Sizeof3D();