74 TGeoXtru::ThreadData_t::ThreadData_t() :
75 fSeg(0), fIz(0), fXc(0), fYc(0), fPoly(0)
82 TGeoXtru::ThreadData_t::~ThreadData_t()
91 TGeoXtru::ThreadData_t& TGeoXtru::GetThreadData()
const
93 if (!fThreadSize) ((TGeoXtru*)
this)->CreateThreadData(1);
94 Int_t tid = TGeoManager::ThreadId();
95 return *fThreadData[tid];
100 void TGeoXtru::ClearThreadData()
const
102 std::lock_guard<std::mutex> guard(fMutex);
103 std::vector<ThreadData_t*>::iterator i = fThreadData.begin();
104 while (i != fThreadData.end())
116 void TGeoXtru::CreateThreadData(Int_t nthreads)
118 std::lock_guard<std::mutex> guard(fMutex);
119 fThreadData.resize(nthreads);
120 fThreadSize = nthreads;
121 for (Int_t tid=0; tid<nthreads; tid++) {
122 if (fThreadData[tid] == 0) {
123 fThreadData[tid] =
new ThreadData_t;
124 ThreadData_t &td = *fThreadData[tid];
125 td.fXc =
new Double_t [fNvert];
126 td.fYc =
new Double_t [fNvert];
127 memcpy(td.fXc, fX, fNvert*
sizeof(Double_t));
128 memcpy(td.fYc, fY, fNvert*
sizeof(Double_t));
129 td.fPoly =
new TGeoPolygon(fNvert);
130 td.fPoly->SetXY(td.fXc, td.fYc);
131 td.fPoly->FinishPolygon();
132 if (tid == 0 && td.fPoly->IsIllegalCheck()) {
133 Error(
"DefinePolygon",
"Shape %s of type XTRU has an illegal polygon.", GetName());
142 void TGeoXtru::SetIz(Int_t iz)
144 GetThreadData().fIz = iz;
149 void TGeoXtru::SetSeg(Int_t iseg)
151 GetThreadData().fSeg = iseg;
171 SetShapeBit(TGeoShape::kGeoXtru);
177 TGeoXtru::TGeoXtru(Int_t nz)
184 fZ(new Double_t[nz]),
185 fScale(new Double_t[nz]),
186 fX0(new Double_t[nz]),
187 fY0(new Double_t[nz]),
191 SetShapeBit(TGeoShape::kGeoXtru);
193 Error(
"ctor",
"Cannot create TGeoXtru %s with less than 2 Z planes", GetName());
194 SetShapeBit(TGeoShape::kGeoBad);
213 TGeoXtru::TGeoXtru(Double_t *param)
227 SetShapeBit(TGeoShape::kGeoXtru);
228 SetDimensions(param);
234 TGeoXtru::TGeoXtru(
const TGeoXtru& xt) :
253 TGeoXtru& TGeoXtru::operator=(
const TGeoXtru& xt)
256 TGeoBBox::operator=(xt);
274 TGeoXtru::~TGeoXtru()
276 if (fX) {
delete[] fX; fX = 0;}
277 if (fY) {
delete[] fY; fY = 0;}
278 if (fZ) {
delete[] fZ; fZ = 0;}
279 if (fScale) {
delete[] fScale; fScale = 0;}
280 if (fX0) {
delete[] fX0; fX0 = 0;}
281 if (fY0) {
delete[] fY0; fY0 = 0;}
288 Double_t TGeoXtru::Capacity()
const
290 ThreadData_t& td = GetThreadData();
292 Double_t capacity = 0;
293 Double_t area, dz, sc1, sc2;
294 TGeoXtru *xtru = (TGeoXtru*)
this;
295 xtru->SetCurrentVertices(0.,0.,1.);
296 area = td.fPoly->Area();
297 for (iz=0; iz<fNz-1; iz++) {
298 dz = fZ[iz+1]-fZ[iz];
299 if (TGeoShape::IsSameWithinTolerance(dz,0))
continue;
302 capacity += (area*dz/3.)*(sc1*sc1+sc1*sc2+sc2*sc2);
310 void TGeoXtru::ComputeBBox()
312 ThreadData_t& td = GetThreadData();
313 if (!fX || !fZ || !fNvert) {
314 Error(
"ComputeBBox",
"In shape %s polygon not defined", GetName());
315 SetShapeBit(TGeoShape::kGeoBad);
318 Double_t zmin = fZ[0];
319 Double_t zmax = fZ[fNz-1];
320 Double_t xmin = TGeoShape::Big();
321 Double_t xmax = -TGeoShape::Big();
322 Double_t ymin = TGeoShape::Big();
323 Double_t ymax = -TGeoShape::Big();
324 for (Int_t i=0; i<fNz; i++) {
325 SetCurrentVertices(fX0[i], fY0[i], fScale[i]);
326 for (Int_t j=0; j<fNvert; j++) {
327 if (td.fXc[j]<xmin) xmin=td.fXc[j];
328 if (td.fXc[j]>xmax) xmax=td.fXc[j];
329 if (td.fYc[j]<ymin) ymin=td.fYc[j];
330 if (td.fYc[j]>ymax) ymax=td.fYc[j];
333 fOrigin[0] = 0.5*(xmin+xmax);
334 fOrigin[1] = 0.5*(ymin+ymax);
335 fOrigin[2] = 0.5*(zmin+zmax);
336 fDX = 0.5*(xmax-xmin);
337 fDY = 0.5*(ymax-ymin);
338 fDZ = 0.5*(zmax-zmin);
344 void TGeoXtru::ComputeNormal(
const Double_t * ,
const Double_t *dir, Double_t *norm)
346 ThreadData_t& td = GetThreadData();
348 memset(norm,0,3*
sizeof(Double_t));
349 norm[2] = (dir[2]>0)?1:-1;
353 GetPlaneVertices(td.fIz, td.fSeg, vert);
354 GetPlaneNormal(vert, norm);
355 Double_t ndotd = norm[0]*dir[0]+norm[1]*dir[1]+norm[2]*dir[2];
366 Bool_t TGeoXtru::Contains(
const Double_t *point)
const
368 ThreadData_t& td = GetThreadData();
370 TGeoXtru *xtru = (TGeoXtru*)
this;
371 if (point[2]<fZ[0])
return kFALSE;
372 if (point[2]>fZ[fNz-1])
return kFALSE;
373 Int_t iz = TMath::BinarySearch(fNz, fZ, point[2]);
374 if (iz<0 || iz==fNz-1)
return kFALSE;
375 if (TGeoShape::IsSameWithinTolerance(point[2],fZ[iz])) {
377 xtru->SetCurrentVertices(fX0[iz],fY0[iz], fScale[iz]);
378 if (td.fPoly->Contains(point))
return kTRUE;
379 if (iz>1 && TGeoShape::IsSameWithinTolerance(fZ[iz],fZ[iz-1])) {
380 xtru->SetCurrentVertices(fX0[iz-1],fY0[iz-1], fScale[iz-1]);
381 return td.fPoly->Contains(point);
382 }
else if (iz<fNz-2 && TGeoShape::IsSameWithinTolerance(fZ[iz],fZ[iz+1])) {
383 xtru->SetCurrentVertices(fX0[iz+1],fY0[iz+1], fScale[iz+1]);
384 return td.fPoly->Contains(point);
387 xtru->SetCurrentZ(point[2], iz);
388 if (TMath::Abs(point[2]-fZ[iz])<TGeoShape::Tolerance() ||
389 TMath::Abs(fZ[iz+1]-point[2])<TGeoShape::Tolerance()) xtru->SetIz(-1);
391 return td.fPoly->Contains(point);
397 Int_t TGeoXtru::DistancetoPrimitive(Int_t px, Int_t py)
399 const Int_t numPoints = fNvert*fNz;
400 return ShapeDistancetoPrimitive(numPoints, px, py);
406 void TGeoXtru::DrawPolygon(Option_t *option)
408 ThreadData_t& td = GetThreadData();
409 if (td.fPoly) td.fPoly->Draw(option);
415 Double_t TGeoXtru::DistToPlane(
const Double_t *point,
const Double_t *dir, Int_t iz, Int_t ivert, Double_t stepmax, Bool_t in)
const
417 ThreadData_t& td = GetThreadData();
424 if (TGeoShape::IsSameWithinTolerance(fZ[iz],fZ[iz+1]) && !in) {
425 TGeoXtru *xtru = (TGeoXtru*)
this;
426 snext = (fZ[iz]-point[2])/dir[2];
427 if (snext<0)
return TGeoShape::Big();
428 pt[0] = point[0]+snext*dir[0];
429 pt[1] = point[1]+snext*dir[1];
430 pt[2] = point[2]+snext*dir[2];
431 if (dir[2] < 0.) xtru->SetCurrentVertices(fX0[iz], fY0[iz], fScale[iz]);
432 else xtru->SetCurrentVertices(fX0[iz+1], fY0[iz+1], fScale[iz+1]);
433 if (!td.fPoly->Contains(pt))
return TGeoShape::Big();
436 GetPlaneVertices(iz, ivert, vert);
437 GetPlaneNormal(vert, norm);
438 Double_t ndotd = norm[0]*dir[0]+norm[1]*dir[1]+norm[2]*dir[2];
440 if (ndotd<=0)
return TGeoShape::Big();
441 safe = (vert[0]-point[0])*norm[0]+
442 (vert[1]-point[1])*norm[1]+
443 (vert[2]-point[2])*norm[2];
444 if (safe<-1.E-8)
return TGeoShape::Big();
447 if (ndotd<=0)
return TGeoShape::Big();
448 safe = (point[0]-vert[0])*norm[0]+
449 (point[1]-vert[1])*norm[1]+
450 (point[2]-vert[2])*norm[2];
451 if (safe<-1.E-8)
return TGeoShape::Big();
454 if (snext>stepmax)
return TGeoShape::Big();
455 if (fZ[iz]<fZ[iz+1]) {
456 znew = point[2] + snext*dir[2];
457 if (znew<fZ[iz])
return TGeoShape::Big();
458 if (znew>fZ[iz+1])
return TGeoShape::Big();
460 pt[0] = point[0]+snext*dir[0];
461 pt[1] = point[1]+snext*dir[1];
462 pt[2] = point[2]+snext*dir[2];
463 if (!IsPointInsidePlane(pt, vert, norm))
return TGeoShape::Big();
464 return TMath::Max(snext, 0.);
471 Double_t TGeoXtru::DistFromInside(
const Double_t *point,
const Double_t *dir, Int_t iact, Double_t step, Double_t *safe)
const
473 ThreadData_t& td = GetThreadData();
474 if (iact<3 && safe) {
475 *safe = Safety(point, kTRUE);
476 if (iact==0)
return TGeoShape::Big();
477 if (iact==1 && step<*safe)
return TGeoShape::Big();
479 TGeoXtru *xtru = (TGeoXtru*)
this;
480 Int_t iz = TMath::BinarySearch(fNz, fZ, point[2]);
496 if (TGeoShape::IsSameWithinTolerance(point[2],fZ[iz])) {
497 if (TGeoShape::IsSameWithinTolerance(fZ[iz],fZ[iz+1]) && dir[2]<0) iz++;
498 else if (TGeoShape::IsSameWithinTolerance(fZ[iz],fZ[iz-1]) && dir[2]>0) iz--;
502 Bool_t convex = td.fPoly->IsConvex();
505 Double_t snext = TGeoShape::Big();
508 Int_t iv, ipl, inext;
510 if (TGeoShape::IsSameWithinTolerance(dir[2],0)) {
511 for (iv=0; iv<fNvert; iv++) {
513 dist = DistToPlane(point,dir,iz,iv,TGeoShape::Big(),kTRUE);
517 if (convex)
return snext;
520 if (snext < 1.E10)
return snext;
521 return TGeoShape::Tolerance();
525 Int_t incseg = (dir[2]>0)?1:-1;
527 Bool_t zexit = kFALSE;
528 while (iz>=0 && iz<fNz-1) {
530 ipl = iz+((incseg+1)>>1);
532 sz = (fZ[ipl]-point[2])/dir[2];
536 pt[0] = point[0]+sz*dir[0];
537 pt[1] = point[1]+sz*dir[1];
538 xtru->SetCurrentVertices(fX0[ipl],fY0[ipl],fScale[ipl]);
539 if (td.fPoly->Contains(pt)) {
541 if (ipl==0 || ipl==fNz-1) {
543 if (convex)
return sz;
548 if (!zexit && TGeoShape::IsSameWithinTolerance(fZ[ipl],fZ[inext])) {
549 xtru->SetCurrentVertices(fX0[inext],fY0[inext],fScale[inext]);
551 if (!td.fPoly->Contains(pt)) {
553 if (convex)
return sz;
565 for (iv=0; iv<fNvert; iv++) {
566 dist = DistToPlane(point,dir,iz,iv,TGeoShape::Big(),kTRUE);
571 if (convex)
return snext;
575 if (zexit)
return snext;
578 return TGeoShape::Tolerance();
585 Double_t TGeoXtru::DistFromOutside(
const Double_t *point,
const Double_t *dir, Int_t iact, Double_t step, Double_t *safe)
const
587 ThreadData_t& td = GetThreadData();
588 if (iact<3 && safe) {
589 *safe = Safety(point, kTRUE);
590 if (iact==0)
return TGeoShape::Big();
591 if (iact==1 && step<*safe)
return TGeoShape::Big();
594 Double_t sdist = TGeoBBox::DistFromOutside(point,dir, fDX, fDY, fDZ, fOrigin, step);
595 if (sdist>=step)
return TGeoShape::Big();
596 Double_t stepmax = step;
597 if (stepmax>TGeoShape::Big()) stepmax = TGeoShape::Big();
599 Double_t dist = TGeoShape::Big();
602 memcpy(pt,point,3*
sizeof(Double_t));
603 TGeoXtru *xtru = (TGeoXtru*)
this;
605 Int_t iz = TMath::BinarySearch(fNz, fZ, point[2]);
607 if (dir[2]<=0)
return TGeoShape::Big();
609 snext = (fZ[0] - point[2])/dir[2];
610 if (snext>stepmax)
return TGeoShape::Big();
611 for (i=0; i<3; i++) pt[i] = point[i] + snext*dir[i];
612 xtru->SetCurrentVertices(fX0[0],fY0[0],fScale[0]);
613 if (td.fPoly->Contains(pt)) {
621 if (dir[2]>=0)
return TGeoShape::Big();
623 snext = (fZ[fNz-1] - point[2])/dir[2];
624 if (snext>stepmax)
return TGeoShape::Big();
625 for (i=0; i<3; i++) pt[i] = point[i] + snext*dir[i];
626 xtru->SetCurrentVertices(fX0[fNz-1],fY0[fNz-1],fScale[fNz-1]);
627 if (td.fPoly->Contains(pt)) {
636 if (!TGeoBBox::Contains(pt)) {
637 dist = TGeoBBox::DistFromOutside(pt,dir,3);
638 if (dist>stepmax)
return TGeoShape::Big();
639 if (dist>1E-6) dist-=1E-6;
641 for (i=0; i<3; i++) pt[i] += dist*dir[i];
642 iz = TMath::BinarySearch(fNz, fZ, pt[2]);
644 else if (iz==fNz-1) iz = fNz-2;
651 Bool_t convex = td.fPoly->IsConvex();
653 if (TGeoShape::IsSameWithinTolerance(dir[2],0)) {
656 for (iv=0; iv<fNvert; iv++) {
657 dist = DistToPlane(pt,dir,iz,iv,stepmax,kFALSE);
660 if (convex)
return (snext+dist);
665 if (hit)
return (snext+stepmax);
666 return TGeoShape::Big();
669 Int_t incseg = (dir[2]>0)?1:-1;
670 while (iz>=0 && iz<fNz-1) {
673 if (TGeoShape::IsSameWithinTolerance(fZ[iz],fZ[iz+1])) xtru->SetIz(-1);
674 for (iv=0; iv<fNvert; iv++) {
675 dist = DistToPlane(pt,dir,iz,iv,stepmax,kFALSE);
679 if (convex)
return (snext+dist);
684 if (hit)
return (snext+stepmax);
687 return TGeoShape::Big();
698 Bool_t TGeoXtru::DefinePolygon(Int_t nvert,
const Double_t *xv,
const Double_t *yv)
701 Error(
"DefinePolygon",
"In shape %s cannot create polygon with less than 3 vertices", GetName());
702 SetShapeBit(TGeoShape::kGeoBad);
705 for (Int_t i=0; i<nvert-1; i++) {
706 for (Int_t j=i+1; j<nvert; j++) {
707 if (TMath::Abs(xv[i]-xv[j])<TGeoShape::Tolerance() &&
708 TMath::Abs(yv[i]-yv[j])<TGeoShape::Tolerance()) {
709 Error(
"DefinePolygon",
"In shape %s 2 vertices cannot be identical",GetName());
710 SetShapeBit(TGeoShape::kGeoBad);
716 if (fX)
delete [] fX;
717 fX =
new Double_t[nvert];
718 if (fY)
delete [] fY;
719 fY =
new Double_t[nvert];
720 memcpy(fX,xv,nvert*
sizeof(Double_t));
721 memcpy(fY,yv,nvert*
sizeof(Double_t));
731 void TGeoXtru::DefineSection(Int_t snum, Double_t z, Double_t x0, Double_t y0, Double_t scale)
733 if ((snum<0) || (snum>=fNz))
return;
737 fScale[snum] = scale;
739 if (fZ[snum]<fZ[snum-1]) {
740 Warning(
"DefineSection",
"In shape: %s, Z position of section "
741 "%i, z=%e, not in increasing order, %i, z=%e",
742 GetName(),snum,fZ[snum],snum-1,fZ[snum-1]);
748 if (TestShapeBit(TGeoShape::kGeoBad)) InspectShape();
755 Double_t TGeoXtru::GetZ(Int_t ipl)
const
757 if (ipl<0 || ipl>(fNz-1)) {
758 Error(
"GetZ",
"In shape %s, ipl=%i out of range (0,%i)",GetName(),ipl,fNz-1);
767 void TGeoXtru::GetPlaneNormal(
const Double_t *vert, Double_t *norm)
const
770 Double_t v1[3], v2[3];
771 v1[0] = vert[9]-vert[0];
772 v1[1] = vert[10]-vert[1];
773 v1[2] = vert[11]-vert[2];
774 v2[0] = vert[3]-vert[0];
775 v2[1] = vert[4]-vert[1];
776 v2[2] = vert[5]-vert[2];
777 norm[0] = v1[1]*v2[2]-v1[2]*v2[1];
778 cross += norm[0]*norm[0];
779 norm[1] = v1[2]*v2[0]-v1[0]*v2[2];
780 cross += norm[1]*norm[1];
781 norm[2] = v1[0]*v2[1]-v1[1]*v2[0];
782 cross += norm[2]*norm[2];
783 if (cross < TGeoShape::Tolerance())
return;
784 cross = 1./TMath::Sqrt(cross);
785 for (Int_t i=0; i<3; i++) norm[i] *= cross;
792 void TGeoXtru::GetPlaneVertices(Int_t iz, Int_t ivert, Double_t *vert)
const
794 ThreadData_t& td = GetThreadData();
796 Int_t iv1 = (ivert+1)%fNvert;
800 if (td.fPoly->IsClockwise()) {
801 x = fX[ivert]*fScale[iz]+fX0[iz];
802 y = fY[ivert]*fScale[iz]+fY0[iz];
806 x = fX[iv1]*fScale[iz]+fX0[iz];
807 y = fY[iv1]*fScale[iz]+fY0[iz];
811 x = fX[iv1]*fScale[iz+1]+fX0[iz+1];
812 y = fY[iv1]*fScale[iz+1]+fY0[iz+1];
816 x = fX[ivert]*fScale[iz+1]+fX0[iz+1];
817 y = fY[ivert]*fScale[iz+1]+fY0[iz+1];
822 x = fX[iv1]*fScale[iz]+fX0[iz];
823 y = fY[iv1]*fScale[iz]+fY0[iz];
827 x = fX[ivert]*fScale[iz]+fX0[iz];
828 y = fY[ivert]*fScale[iz]+fY0[iz];
832 x = fX[ivert]*fScale[iz+1]+fX0[iz+1];
833 y = fY[ivert]*fScale[iz+1]+fY0[iz+1];
837 x = fX[iv1]*fScale[iz+1]+fX0[iz+1];
838 y = fY[iv1]*fScale[iz+1]+fY0[iz+1];
847 Bool_t TGeoXtru::IsPointInsidePlane(
const Double_t *point, Double_t *vert, Double_t *norm)
const
849 Double_t v1[3], v2[3];
852 for (Int_t i=0; i<4; i++) {
855 v1[0] = point[0]-vert[j];
856 v1[1] = point[1]-vert[j+1];
857 v1[2] = point[2]-vert[j+2];
858 v2[0] = vert[k]-vert[j];
859 v2[1] = vert[k+1]-vert[j+1];
860 v2[2] = vert[k+2]-vert[j+2];
861 cross = (v1[1]*v2[2]-v1[2]*v2[1])*norm[0]+
862 (v1[2]*v2[0]-v1[0]*v2[2])*norm[1]+
863 (v1[0]*v2[1]-v1[1]*v2[0])*norm[2];
864 if (cross<0)
return kFALSE;
872 void TGeoXtru::InspectShape()
const
874 printf(
"*** Shape %s: TGeoXtru ***\n", GetName());
875 printf(
" Nz = %i\n", fNz);
876 printf(
" List of (x,y) of polygon vertices:\n");
877 for (Int_t ivert = 0; ivert<fNvert; ivert++)
878 printf(
" x = %11.5f y = %11.5f\n", fX[ivert],fY[ivert]);
879 for (Int_t ipl=0; ipl<fNz; ipl++)
880 printf(
" plane %i: z=%11.5f x0=%11.5f y0=%11.5f scale=%11.5f\n", ipl, fZ[ipl], fX0[ipl], fY0[ipl], fScale[ipl]);
881 printf(
" Bounding box:\n");
882 TGeoBBox::InspectShape();
889 TBuffer3D *TGeoXtru::MakeBuffer3D()
const
892 Int_t nvert = GetNvert();
893 Int_t nbPnts = nz*nvert;
894 Int_t nbSegs = nvert*(2*nz-1);
895 Int_t nbPols = nvert*(nz-1)+2;
897 TBuffer3D* buff =
new TBuffer3D(TBuffer3DTypes::kGeneric,
898 nbPnts, 3*nbPnts, nbSegs, 3*nbSegs, nbPols, 6*(nbPols-2)+2*(2+nvert));
901 SetPoints(buff->fPnts);
902 SetSegsAndPols(*buff);
911 void TGeoXtru::SetSegsAndPols(TBuffer3D &buff)
const
914 Int_t nvert = GetNvert();
915 Int_t c = GetBasicColor();
918 Int_t indx, indx2, k;
920 for (i=0; i<nz; i++) {
924 for (j=0; j<nvert; j++) {
926 buff.fSegs[indx++] = c;
927 buff.fSegs[indx++] = indx2+j;
928 buff.fSegs[indx++] = indx2+k;
931 for (i=0; i<nz-1; i++) {
935 for (j=0; j<nvert; j++) {
937 buff.fSegs[indx++] = c;
938 buff.fSegs[indx++] = indx2+j;
939 buff.fSegs[indx++] = indx2+k;
946 for (i=0; i<nz-1; i++) {
948 for (j=0; j<nvert; j++) {
950 buff.fPols[indx++] = c+j%3;
951 buff.fPols[indx++] = 4;
952 buff.fPols[indx++] = indx2+j;
953 buff.fPols[indx++] = nz*nvert+indx2+k;
954 buff.fPols[indx++] = indx2+nvert+j;
955 buff.fPols[indx++] = nz*nvert+indx2+j;
958 buff.fPols[indx++] = c+2;
959 buff.fPols[indx++] = nvert;
961 for (j = nvert - 1; j >= 0; --j) {
962 buff.fPols[indx++] = indx2+j;
965 buff.fPols[indx++] = c;
966 buff.fPols[indx++] = nvert;
967 indx2 = (nz-1)*nvert;
969 for (j=0; j<nvert; j++) {
970 buff.fPols[indx++] = indx2+j;
977 Double_t TGeoXtru::SafetyToSector(
const Double_t *point, Int_t iz, Double_t safmin, Bool_t in)
979 ThreadData_t& td = GetThreadData();
980 Double_t safz = TGeoShape::Big();
984 Double_t safe = TGeoShape::Big();
986 if (TGeoShape::IsSameWithinTolerance(fZ[iz],fZ[iz+1])) {
987 safz = TMath::Abs(point[2]-fZ[iz]);
988 if (safz>safmin)
return TGeoShape::Big();
989 SetCurrentVertices(fX0[iz], fY0[iz], fScale[iz]);
990 saf1 = td.fPoly->Safety(point, iseg);
991 in1 = td.fPoly->Contains(point);
993 SetCurrentVertices(fX0[iz+1], fY0[iz+1], fScale[iz+1]);
994 saf2 = td.fPoly->Safety(point, iseg);
995 in2 = td.fPoly->Contains(point);
996 if ((in1&!in2)|(in2&!in1)) {
999 safe = TMath::Min(saf1,saf2);
1000 safe = TMath::Max(safe, safz);
1002 if (safe>safmin)
return TGeoShape::Big();
1006 safz = fZ[iz]-point[2];
1007 if (safz>safmin)
return TGeoShape::Big();
1009 saf1 = point[2]-fZ[iz+1];
1010 if (saf1>safmin)
return TGeoShape::Big();
1012 safz = TMath::Max(safz, saf1);
1019 Bool_t found = kFALSE;
1023 for (iseg=0; iseg<fNvert; iseg++) {
1024 GetPlaneVertices(iz,iseg,vert);
1025 GetPlaneNormal(vert, norm);
1026 saf1 = (point[0]-vert[0])*norm[0]+(point[1]-vert[1])*norm[1]+(point[2]-vert[2])*norm[2];
1027 if (in) saf1 = -saf1;
1029 if (saf1<-1.E-8)
continue;
1030 safe = TMath::Max(safz, saf1);
1031 safe = TMath::Abs(safe);
1032 if (safe>safmin)
continue;
1036 if (found)
return safmin;
1037 return TGeoShape::Big();
1045 Double_t TGeoXtru::Safety(
const Double_t *point, Bool_t in)
const
1047 Double_t safmin = TGeoShape::Big();
1049 Double_t safz = TGeoShape::Big();
1050 TGeoXtru *xtru = (TGeoXtru*)
this;
1053 safmin = TMath::Min(point[2]-fZ[0], fZ[fNz-1]-point[2]);
1054 for (iz=0; iz<fNz-1; iz++) {
1055 safe = xtru->SafetyToSector(point, iz, safmin, in);
1056 if (safe<safmin) safmin = safe;
1061 if (!TGeoBBox::Contains(point))
return TGeoBBox::Safety(point,in);
1062 iz = TMath::BinarySearch(fNz, fZ, point[2]);
1065 safz = fZ[0] - point[2];
1069 safz = point[2] - fZ[fNz-1];
1074 for (i=iz; i<fNz-1; i++) {
1075 safe = xtru->SafetyToSector(point,i,safmin, in);
1076 if (safe<safmin) safmin=safe;
1079 for (i=iz-1; i>=0; i--) {
1080 safe = xtru->SafetyToSector(point,i,safmin, in);
1081 if (safe<safmin) safmin=safe;
1083 safe = TMath::Min(safmin, safz);
1090 void TGeoXtru::SavePrimitive(std::ostream &out, Option_t * )
1092 if (TObject::TestBit(kGeoSavePrimitive))
return;
1093 out <<
" // Shape: " << GetName() <<
" type: " << ClassName() << std::endl;
1094 out <<
" nz = " << fNz <<
";" << std::endl;
1095 out <<
" nvert = " << fNvert <<
";" << std::endl;
1096 out <<
" TGeoXtru *xtru = new TGeoXtru(nz);" << std::endl;
1097 out <<
" xtru->SetName(\"" << GetName() <<
"\");" << std::endl;
1099 for (i=0; i<fNvert; i++) {
1100 out <<
" xvert[" << i <<
"] = " << fX[i] <<
"; yvert[" << i <<
"] = " << fY[i] <<
";" << std::endl;
1102 out <<
" xtru->DefinePolygon(nvert,xvert,yvert);" << std::endl;
1103 for (i=0; i<fNz; i++) {
1104 out <<
" zsect = " << fZ[i] <<
";" << std::endl;
1105 out <<
" x0 = " << fX0[i] <<
";" << std::endl;
1106 out <<
" y0 = " << fY0[i] <<
";" << std::endl;
1107 out <<
" scale0 = " << fScale[i] <<
";" << std::endl;
1108 out <<
" xtru->DefineSection(" << i <<
",zsect,x0,y0,scale0);" << std::endl;
1110 out <<
" TGeoShape *" << GetPointerName() <<
" = xtru;" << std::endl;
1111 TObject::SetBit(TGeoShape::kGeoSavePrimitive);
1117 void TGeoXtru::SetCurrentZ(Double_t z, Int_t iz)
1119 Double_t x0, y0, scale, a, b;
1123 Double_t invdz = 1./(fZ[ind2]-fZ[ind1]);
1124 a = (fX0[ind1]*fZ[ind2]-fX0[ind2]*fZ[ind1])*invdz;
1125 b = (fX0[ind2]-fX0[ind1])*invdz;
1127 a = (fY0[ind1]*fZ[ind2]-fY0[ind2]*fZ[ind1])*invdz;
1128 b = (fY0[ind2]-fY0[ind1])*invdz;
1130 a = (fScale[ind1]*fZ[ind2]-fScale[ind2]*fZ[ind1])*invdz;
1131 b = (fScale[ind2]-fScale[ind1])*invdz;
1133 SetCurrentVertices(x0,y0,scale);
1139 void TGeoXtru::SetCurrentVertices(Double_t x0, Double_t y0, Double_t scale)
1141 ThreadData_t& td = GetThreadData();
1142 for (Int_t i=0; i<fNvert; i++) {
1143 td.fXc[i] = scale*fX[i] + x0;
1144 td.fYc[i] = scale*fY[i] + y0;
1161 void TGeoXtru::SetDimensions(Double_t *param)
1163 fNz = (Int_t)param[0];
1165 Error(
"SetDimensions",
"Cannot create TGeoXtru %s with less than 2 Z planes",GetName());
1166 SetShapeBit(TGeoShape::kGeoBad);
1169 if (fZ)
delete [] fZ;
1170 if (fScale)
delete [] fScale;
1171 if (fX0)
delete [] fX0;
1172 if (fY0)
delete [] fY0;
1173 fZ =
new Double_t[fNz];
1174 fScale =
new Double_t[fNz];
1175 fX0 =
new Double_t[fNz];
1176 fY0 =
new Double_t[fNz];
1178 for (Int_t i=0; i<fNz; i++)
1179 DefineSection(i, param[1+4*i], param[2+4*i], param[3+4*i], param[4+4*i]);
1185 void TGeoXtru::SetPoints(Double_t *points)
const
1187 ThreadData_t& td = GetThreadData();
1190 TGeoXtru *xtru = (TGeoXtru*)
this;
1192 for (i = 0; i < fNz; i++) {
1193 xtru->SetCurrentVertices(fX0[i], fY0[i], fScale[i]);
1194 if (td.fPoly->IsClockwise()) {
1195 for (j = 0; j < fNvert; j++) {
1196 points[indx++] = td.fXc[j];
1197 points[indx++] = td.fYc[j];
1198 points[indx++] = fZ[i];
1201 for (j = 0; j < fNvert; j++) {
1202 points[indx++] = td.fXc[fNvert-1-j];
1203 points[indx++] = td.fYc[fNvert-1-j];
1204 points[indx++] = fZ[i];
1214 void TGeoXtru::SetPoints(Float_t *points)
const
1216 ThreadData_t& td = GetThreadData();
1219 TGeoXtru *xtru = (TGeoXtru*)
this;
1221 for (i = 0; i < fNz; i++) {
1222 xtru->SetCurrentVertices(fX0[i], fY0[i], fScale[i]);
1223 if (td.fPoly->IsClockwise()) {
1224 for (j = 0; j < fNvert; j++) {
1225 points[indx++] = td.fXc[j];
1226 points[indx++] = td.fYc[j];
1227 points[indx++] = fZ[i];
1230 for (j = 0; j < fNvert; j++) {
1231 points[indx++] = td.fXc[fNvert-1-j];
1232 points[indx++] = td.fYc[fNvert-1-j];
1233 points[indx++] = fZ[i];
1243 void TGeoXtru::GetMeshNumbers(Int_t &nvert, Int_t &nsegs, Int_t &npols)
const
1246 Int_t nv = GetNvert();
1248 nsegs = nv*(2*nz-1);
1249 npols = nv*(nz-1)+2;
1255 Int_t TGeoXtru::GetNmeshVertices()
const
1257 Int_t numPoints = fNz*fNvert;
1264 void TGeoXtru::Sizeof3D()
const
1271 const TBuffer3D & TGeoXtru::GetBuffer3D(Int_t reqSections, Bool_t localFrame)
const
1273 static TBuffer3D buffer(TBuffer3DTypes::kGeneric);
1275 TGeoBBox::FillBuffer3D(buffer, reqSections, localFrame);
1277 if (reqSections & TBuffer3D::kRawSizes) {
1279 Int_t nvert = GetNvert();
1280 Int_t nbPnts = nz*nvert;
1281 Int_t nbSegs = nvert*(2*nz-1);
1282 Int_t nbPols = nvert*(nz-1)+2;
1283 if (buffer.SetRawSizes(nbPnts, 3*nbPnts, nbSegs, 3*nbSegs, nbPols, 6*(nbPols-2)+2*(2+nvert))) {
1284 buffer.SetSectionsValid(TBuffer3D::kRawSizes);
1288 if ((reqSections & TBuffer3D::kRaw) && buffer.SectionsValid(TBuffer3D::kRawSizes)) {
1289 SetPoints(buffer.fPnts);
1290 if (!buffer.fLocalFrame) {
1291 TransformPoints(buffer.fPnts, buffer.NbPnts());
1294 SetSegsAndPols(buffer);
1295 buffer.SetSectionsValid(TBuffer3D::kRaw);
1306 void TGeoXtru::Contains_v(
const Double_t *points, Bool_t *inside, Int_t vecsize)
const
1308 for (Int_t i=0; i<vecsize; i++) inside[i] = Contains(&points[3*i]);
1316 void TGeoXtru::ComputeNormal_v(
const Double_t *points,
const Double_t *dirs, Double_t *norms, Int_t vecsize)
1318 for (Int_t i=0; i<vecsize; i++) ComputeNormal(&points[3*i], &dirs[3*i], &norms[3*i]);
1324 void TGeoXtru::DistFromInside_v(
const Double_t *points,
const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step)
const
1326 for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromInside(&points[3*i], &dirs[3*i], 3, step[i]);
1332 void TGeoXtru::DistFromOutside_v(
const Double_t *points,
const Double_t *dirs, Double_t *dists, Int_t vecsize, Double_t* step)
const
1334 for (Int_t i=0; i<vecsize; i++) dists[i] = DistFromOutside(&points[3*i], &dirs[3*i], 3, step[i]);
1342 void TGeoXtru::Safety_v(
const Double_t *points,
const Bool_t *inside, Double_t *safe, Int_t vecsize)
const
1344 for (Int_t i=0; i<vecsize; i++) safe[i] = Safety(&points[3*i], inside[i]);