16 ClassImp(TGraphDelaunay);
49 TGraphDelaunay::TGraphDelaunay()
50 : TNamed(
"TGraphDelaunay",
"TGraphDelaunay")
86 TGraphDelaunay::TGraphDelaunay(TGraph2D *g)
87 : TNamed(
"TGraphDelaunay",
"TGraphDelaunay")
90 fX = fGraph2D->GetX();
91 fY = fGraph2D->GetY();
92 fZ = fGraph2D->GetZ();
93 fNpoints = fGraph2D->GetN();
123 TGraphDelaunay::~TGraphDelaunay()
125 if (fPTried)
delete [] fPTried;
126 if (fNTried)
delete [] fNTried;
127 if (fMTried)
delete [] fMTried;
128 if (fHullPoints)
delete [] fHullPoints;
129 if (fOrder)
delete [] fOrder;
130 if (fDist)
delete [] fDist;
131 if (fXN)
delete [] fXN;
132 if (fYN)
delete [] fYN;
148 Double_t TGraphDelaunay::ComputeZ(Double_t x, Double_t y)
155 CreateTrianglesDataStructure();
162 xx = (x+fXoffset)*fXScaleFactor;
163 yy = (y+fYoffset)*fYScaleFactor;
164 Double_t zz = Interpolate(xx, yy);
168 if (zz==0) zz = Interpolate(xx+0.0001, yy);
178 void TGraphDelaunay::CreateTrianglesDataStructure()
183 Double_t xmax = fGraph2D->GetXmax();
184 Double_t ymax = fGraph2D->GetYmax();
185 Double_t xmin = fGraph2D->GetXmin();
186 Double_t ymin = fGraph2D->GetYmin();
187 fXoffset = -(xmax+xmin)/2.;
188 fYoffset = -(ymax+ymin)/2.;
189 fXScaleFactor = 1./(xmax-xmin);
190 fYScaleFactor = 1./(ymax-ymin);
191 fXNmax = (xmax+fXoffset)*fXScaleFactor;
192 fXNmin = (xmin+fXoffset)*fXScaleFactor;
193 fYNmax = (ymax+fYoffset)*fYScaleFactor;
194 fYNmin = (ymin+fYoffset)*fYScaleFactor;
195 fXN =
new Double_t[fNpoints+1];
196 fYN =
new Double_t[fNpoints+1];
197 for (Int_t n=0; n<fNpoints; n++) {
198 fXN[n+1] = (fX[n]+fXoffset)*fXScaleFactor;
199 fYN[n+1] = (fY[n]+fYoffset)*fYScaleFactor;
205 fTriedSize = 2*fNpoints;
206 fPTried =
new Int_t[fTriedSize];
207 fNTried =
new Int_t[fTriedSize];
208 fMTried =
new Int_t[fTriedSize];
215 Bool_t TGraphDelaunay::Enclose(Int_t t1, Int_t t2, Int_t t3, Int_t e)
const
217 Double_t x[4],y[4],xp, yp;
228 return TMath::IsInside(xp, yp, 4, x, y);
237 void TGraphDelaunay::FileIt(Int_t p, Int_t n, Int_t m)
240 Int_t tmp, ps = p, ns = n, ms = m;
245 if (ns > ps) { tmp = ps; ps = ns; ns = tmp; swap = kTRUE;}
246 if (ms > ns) { tmp = ns; ns = ms; ms = tmp; swap = kTRUE;}
250 if (fNdt>=fTriedSize) {
251 Int_t newN = 2*fTriedSize;
252 Int_t *savep =
new Int_t [newN];
253 Int_t *saven =
new Int_t [newN];
254 Int_t *savem =
new Int_t [newN];
255 memcpy(savep,fPTried,fTriedSize*
sizeof(Int_t));
256 memset(&savep[fTriedSize],0,(newN-fTriedSize)*
sizeof(Int_t));
258 memcpy(saven,fNTried,fTriedSize*
sizeof(Int_t));
259 memset(&saven[fTriedSize],0,(newN-fTriedSize)*
sizeof(Int_t));
261 memcpy(savem,fMTried,fTriedSize*
sizeof(Int_t));
262 memset(&savem[fTriedSize],0,(newN-fTriedSize)*
sizeof(Int_t));
272 fPTried[fNdt-1] = ps;
273 fNTried[fNdt-1] = ns;
274 fMTried[fNdt-1] = ms;
290 void TGraphDelaunay::FindAllTriangles()
292 if (fAllTri)
return;
else fAllTri = kTRUE;
294 Double_t xcntr,ycntr,xm,ym,xx,yy;
295 Double_t sx,sy,nx,ny,mx,my,mdotn,nn,a;
296 Int_t t1,t2,pa,na,ma,pb,nb,mb,p1=0,p2=0,m,n,p3=0;
298 Double_t alittlebit = 0.0001;
306 for (n=1; n<=fNhull; n++) {
307 xcntr = xcntr+fXN[fHullPoints[n-1]];
308 ycntr = ycntr+fYN[fHullPoints[n-1]];
310 xcntr = xcntr/fNhull+alittlebit;
311 ycntr = ycntr/fNhull+alittlebit;
313 Interpolate(xcntr,ycntr);
331 for (t2=1; t2<=fNdt; t2++) {
338 if ((pa==pb && na==nb) || (pa==pb && na==mb) || (pa==nb && na==mb)) {
341 }
else if ((pa==pb && ma==nb) || (pa==pb && ma==mb) || (pa==nb && ma==mb)) {
344 }
else if ((na==pb && ma==nb) || (na==pb && ma==mb) || (na==nb && ma==mb)) {
351 if (s[0] && s[1] && s[2])
continue;
357 for (m=1; m<=3; m++) {
374 xm = (fXN[p1]+fXN[p2])/2.;
375 ym = (fYN[p1]+fYN[p2])/2.;
379 sx = fXN[p1]-fXN[p2];
380 sy = fYN[p1]-fYN[p2];
385 nn = TMath::Sqrt(nx*nx+ny*ny);
399 a = TMath::Abs(TMath::Max(alittlebit*xm,alittlebit*ym));
421 void TGraphDelaunay::FindHull()
426 if (!fHullPoints) fHullPoints =
new Int_t[fNpoints];
429 for(n=1; n<=fNpoints; n++) {
438 fHullPoints[nhull_tmp-1] = n;
448 Bool_t TGraphDelaunay::InHull(Int_t e, Int_t x)
const
450 Int_t n1,n2,n,m,ntry;
451 Double_t lastdphi,dd1,dd2,dx1,dx2,dx3,dy1,dy2,dy3;
452 Double_t u,v,vNv1,vNv2,phi1,phi2,dphi,xx,yy;
454 Bool_t deTinhull = kFALSE;
478 }
else if (n2 == x) {
487 phi1 = TMath::ATan2(dy1,dx1);
488 phi2 = TMath::ATan2(dy2,dx2);
489 dphi = (phi1-phi2)-((Int_t)((phi1-phi2)/TMath::TwoPi())*TMath::TwoPi());
490 if (dphi < 0) dphi = dphi+TMath::TwoPi();
492 for (n=1; n<=ntry; n++) {
495 m = fHullPoints[n-1];
499 if ((m!=n1) && (m!=n2) && (m!=x)) {
509 dd1 = (dx2*dy1-dx1*dy2);
510 dd2 = (dx1*dy2-dx2*dy1);
513 u = (dx2*dy3-dx3*dy2)/dd1;
514 v = (dx1*dy3-dx3*dy1)/dd2;
515 if ((u<0) || (v<0)) {
520 vNv1 = (dx1*dx3+dy1*dy3)/TMath::Sqrt(dx1*dx1+dy1*dy1);
521 vNv2 = (dx2*dx3+dy2*dy3)/TMath::Sqrt(dx2*dx2+dy2*dy2);
524 phi1 = TMath::ATan2(dy3,dx3);
525 phi2 = TMath::ATan2(dy2,dx2);
528 phi1 = TMath::ATan2(dy1,dx1);
529 phi2 = TMath::ATan2(dy3,dx3);
531 dphi = (phi1-phi2)-((Int_t)((phi1-phi2)/TMath::TwoPi())*TMath::TwoPi());
532 if (dphi < 0) dphi = dphi+TMath::TwoPi();
533 if (((dphi-TMath::Pi())*(lastdphi-TMath::Pi())) < 0) {
556 Double_t TGraphDelaunay::InterpolateOnPlane(Int_t TI1, Int_t TI2, Int_t TI3, Int_t e)
const
560 Double_t x1,x2,x3,y1,y2,y3,f1,f2,f3,u,v,w;
569 if (t2 > t1) { tmp = t1; t1 = t2; t2 = tmp; swap = kTRUE;}
570 if (t3 > t2) { tmp = t2; t2 = t3; t3 = tmp; swap = kTRUE;}
582 u = (f1*(y2-y3)+f2*(y3-y1)+f3*(y1-y2))/(x1*(y2-y3)+x2*(y3-y1)+x3*(y1-y2));
583 v = (f1*(x2-x3)+f2*(x3-x1)+f3*(x1-x2))/(y1*(x2-x3)+y2*(x3-x1)+y3*(x1-x2));
586 return u*fXN[e]+v*fYN[e]+w;
595 Double_t TGraphDelaunay::Interpolate(Double_t xx, Double_t yy)
599 Int_t it, ntris_tried, p, n, m;
600 Int_t i,j,k,l,z,f,d,o1,o2,a,b,t1,t2,t3;
601 Int_t ndegen=0,degen=0,fdegen=0,o1degen=0,o2degen=0;
603 Double_t d1,d2,d3,c1,c2,dko1,dko2,dfo1;
604 Double_t dfo2,sin_sum,cfo1k,co2o1k,co2o1f;
607 Double_t dx1,dx2,dx3,dy1,dy2,dy3,u,v,dxz[3],dyz[3];
611 CreateTrianglesDataStructure();
618 fOrder =
new Int_t[fNpoints];
619 fDist =
new Double_t[fNpoints];
633 if ((xx>fXNmax) || (xx<fXNmin) || (yy>fYNmax) || (yy<fYNmin))
return thevalue;
636 for (it=1; it<=fNdt; it++) {
642 if (Enclose(p,n,m,0)) {
644 thevalue = InterpolateOnPlane(p,n,m,0);
650 shouldbein = InHull(0,-1);
651 if (!shouldbein)
return thevalue;
656 for (it=1; it<=fNpoints; it++) {
659 fDist[it-1] = TMath::Sqrt((xx-vxN)*(xx-vxN)+(yy-vyN)*(yy-vyN));
663 TMath::Sort(fNpoints, fDist, fOrder, kFALSE);
664 for (it=0; it<fNpoints; it++) fOrder[it]++;
668 for (k=3; k<=fNpoints; k++) {
670 for (j=2; j<=k-1; j++) {
672 for (i=1; i<=j-1; i++) {
674 if (ntris_tried > fMaxIter) {
683 d1 = TMath::Sqrt((fXN[p]-fXN[n])*(fXN[p]-fXN[n])+(fYN[p]-fYN[n])*(fYN[p]-fYN[n]));
684 d2 = TMath::Sqrt((fXN[p]-fXN[m])*(fXN[p]-fXN[m])+(fYN[p]-fYN[m])*(fYN[p]-fYN[m]));
685 d3 = TMath::Sqrt((fXN[n]-fXN[m])*(fXN[n]-fXN[m])+(fYN[n]-fYN[m])*(fYN[n]-fYN[m]));
686 if ((d1+d2<=d3) || (d1+d3<=d2) || (d2+d3<=d1))
goto L90;
689 if (!Enclose(p,n,m,0))
goto L90;
699 for ( z=1; z<=fNpoints; z++) {
700 if ((z==p) || (z==n) || (z==m))
goto L50;
706 for (l=1; l<=fNpoints; l++) {
707 if (fOrder[l-1] == z) {
708 if ((l<i) || (l<j) || (l<k)) {
713 if (Enclose(p,n,m,z))
goto L90;
723 if (((fXN[p]-fXN[z])*(fYN[p]-fYN[n])) == ((fYN[p]-fYN[z])*(fXN[p]-fXN[n]))) {
727 }
else if (((fXN[p]-fXN[z])*(fYN[p]-fYN[m])) == ((fYN[p]-fYN[z])*(fXN[p]-fXN[m]))) {
731 }
else if (((fXN[n]-fXN[z])*(fYN[n]-fYN[m])) == ((fYN[n]-fYN[z])*(fXN[n]-fXN[m]))) {
742 if (fXN[a] != fXN[b]) {
743 if (((fXN[z]-fXN[a])*(fXN[z]-fXN[b])) < 0) {
745 }
else if (((fXN[z]-fXN[a])*(fXN[z]-fXN[b])) == 0) {
751 Warning(
"Interpolate",
"Two of these three points are coincident %d %d %d",a,b,z);
754 if (((fYN[z]-fYN[a])*(fYN[z]-fYN[b])) < 0) {
756 }
else if (((fYN[z]-fYN[a])*(fYN[z]-fYN[b])) == 0) {
758 Warning(
"Interpolate",
"Two of these three points are coincident %d %d %d",a,b,z);
769 dxz[0] = fXN[p]-fXN[z];
770 dyz[0] = fYN[p]-fYN[z];
771 dxz[1] = fXN[n]-fXN[z];
772 dyz[1] = fYN[n]-fYN[z];
773 dxz[2] = fXN[m]-fXN[z];
774 dyz[2] = fYN[m]-fYN[z];
775 for(l=1; l<=3; l++) {
787 u = (dy3*dx2-dx3*dy2)*(dy1*dx2-dx1*dy2);
788 v = (dy3*dx1-dx3*dy1)*(dy2*dx1-dx2*dy1);
790 if ((u>=0) && (v>=0)) {
818 cfo1k = ((fXN[f]-fXN[o1])*(fXN[z]-fXN[o1])+(fYN[f]-fYN[o1])*(fYN[z]-fYN[o1]))/
819 TMath::Sqrt(((fXN[f]-fXN[o1])*(fXN[f]-fXN[o1])+(fYN[f]-fYN[o1])*(fYN[f]-fYN[o1]))*
820 ((fXN[z]-fXN[o1])*(fXN[z]-fXN[o1])+(fYN[z]-fYN[o1])*(fYN[z]-fYN[o1])));
821 co2o1k = ((fXN[o2]-fXN[o1])*(fXN[z]-fXN[o1])+(fYN[o2]-fYN[o1])*(fYN[z]-fYN[o1]))/
822 TMath::Sqrt(((fXN[o2]-fXN[o1])*(fXN[o2]-fXN[o1])+(fYN[o2]-fYN[o1])*(fYN[o2]-fYN[o1]))*
823 ((fXN[z]-fXN[o1])*(fXN[z]-fXN[o1]) + (fYN[z]-fYN[o1])*(fYN[z]-fYN[o1])));
824 co2o1f = ((fXN[o2]-fXN[o1])*(fXN[f]-fXN[o1])+(fYN[o2]-fYN[o1])*(fYN[f]-fYN[o1]))/
825 TMath::Sqrt(((fXN[o2]-fXN[o1])*(fXN[o2]-fXN[o1])+(fYN[o2]-fYN[o1])*(fYN[o2]-fYN[o1]))*
826 ((fXN[f]-fXN[o1])*(fXN[f]-fXN[o1]) + (fYN[f]-fYN[o1])*(fYN[f]-fYN[o1]) ));
827 if ((cfo1k>co2o1k) || (cfo1k>co2o1f)) {
834 dko1 = TMath::Sqrt((fXN[z]-fXN[o1])*(fXN[z]-fXN[o1])+(fYN[z]-fYN[o1])*(fYN[z]-fYN[o1]));
835 dko2 = TMath::Sqrt((fXN[z]-fXN[o2])*(fXN[z]-fXN[o2])+(fYN[z]-fYN[o2])*(fYN[z]-fYN[o2]));
836 dfo1 = TMath::Sqrt((fXN[f]-fXN[o1])*(fXN[f]-fXN[o1])+(fYN[f]-fYN[o1])*(fYN[f]-fYN[o1]));
837 dfo2 = TMath::Sqrt((fXN[f]-fXN[o2])*(fXN[f]-fXN[o2])+(fYN[f]-fYN[o2])*(fYN[f]-fYN[o2]));
838 c1 = ((fXN[z]-fXN[o1])*(fXN[z]-fXN[o2])+(fYN[z]-fYN[o1])*(fYN[z]-fYN[o2]))/dko1/dko2;
839 c2 = ((fXN[f]-fXN[o1])*(fXN[f]-fXN[o2])+(fYN[f]-fYN[o1])*(fYN[f]-fYN[o2]))/dfo1/dfo2;
840 sin_sum = c1*TMath::Sqrt(1-c2*c2)+c2*TMath::Sqrt(1-c1*c1);
843 if (sin_sum < -1.E-6) {
846 }
else if (TMath::Abs(sin_sum) <= 1.E-6) {
880 if ((fZ[o1-1]+fZ[o2-1]) > (fZ[d-1]+fZ[f-1])) {
895 if (Enclose(f,d,o1,0)) {
912 thevalue = InterpolateOnPlane(t1,t2,t3,0);
921 "Point outside hull when expected inside: this point could be dodgy %g %g %d",
922 xx, yy, ntris_tried);
932 void TGraphDelaunay::SetMaxIter(Int_t n)
943 void TGraphDelaunay::SetMarginBinsContent(Double_t z)