How to find out whether a data point is inside an ellipse (TEllipse)

I use the class TEllipse as 95% contour, generated from a set of points in two dimensions. How can I find out whether a new point is inside the ellipse. I want to use physical coordinates, not pixels on my screen.

Are you sure you are using TEllipse ? I am asking because TEllipse is not defined by a set of points but by the box enclosing it. Maybe you are using TGraph ?

TGraph has the IsInside method which does what you are looking for.

Given that you defined an TEllipse like

TEllipse *el = new TEllipse(x_c, y_c, r_x, r_y);

You can verify with just an if statement a new point with coordinates x,y is inside the ellipse.

if( ( (x - x_c)*(x - x_c)/r_x/r_x +  (y - y_c)*(y - y_c)/r_y/r_y)<=1 )
    cout<<"is inside" <<endl;
else
    cout<< "is outside" << endl;

Dear Dilicus,

thanks for the formula for the ellipse. I actually hoped that there is a
method in the TEllipse class to return “Inside” or “Outside”. In
addition in my case the ellipse is tilted by an angle theta, so that I
have to use a rotation in addition to the formula you showed. This is
actually the argument number 7 when calling TEllipse: TEllipse(x_c,
y_c, r_x, r_y, phimin, phimax, theta).

So in my case: x → x cos(theta) -y sin(theta) and y-> x sin(theta) - y
cos(theta). It would be great if a method (“Inside”) would be integrated
in the TEllipse class. For the moment I have to do it “the hard way”, as
you suggest, with my rotations added.

Best

Christian

1 Like

Agreed!

Note it is a bit more tricky than just taking into account the tilting, as TEllipse allows to produce this kind of polygon:

Screenshot 2024-01-26 at 11.00.59

Dear Olivier,

indeed, cutting out a sector from the ellipse (arguments 5 = phimin and 6 = phimax) is an additional challenge for the “Inside” method . Nevertheless, I am happy to read that the ROOT team will consider this additional feature for TEllipse.

Best

Christian

I have implemented it:

Macro inside.C

TEllipse *el;

void EPoint(double x, double y) {
   auto p = new TMarker(x,y,20);
   p->Draw();
   if (el->IsInside(x,y)) {
      p->SetMarkerColor(kGreen);
      printf("The point (%g, %g) is inside the ellipse\n",x,y);
   } else {
      p->SetMarkerColor(kRed);
      printf("The point (%g, %g) is outside the ellipse\n",x,y);
   }
}

void inside(){
   el = new TEllipse(0.75, 0.25, .2,.15,45,315,62);
   el->SetLineColor(4);
   el->Draw();
   EPoint(.5,.5);
   EPoint(.7,.3);
   EPoint(.8,.2);
   EPoint(.8,.3);
}

But for completeness, I will also implement it for other primitives like TBox etc … I’ll make a PR once I have them.

I made an issue: Implement IsInside for TEllipse · Issue #14453 · root-project/root · GitHub

Dear Olivier,

great, thanks!

I am looking forward to the PR and the new version of ROOT to download via snap!

Cheers

Christian

The PR is here: Implement some missing "IsInside" by couet · Pull Request #14456 · root-project/root · GitHub

I added a new tutorial testing IsInside for various classes.

void inside(){
   auto el = new TEllipse(0.75, 0.25, .2,.15,45,315,62);
   el->Draw();

   auto gr = new TGraph();
   double gr_x1[5] = { 0.1, 0.3388252, 0.03796561, 0.4176218, 0.1 };
   double gr_y1[5] = { 0.5, 0.9644737, 0.7776316, 0.6960526, 0.5 };
   gr = new TGraph(5,gr_x1,gr_y1);
   gr->Draw("L");

   auto bx = new TBox(.7,.8,.9,.95);
   bx->Draw();

   auto pv = new TPave(.05,.1,.3,.2);
   pv->Draw();

   auto di = new TDiamond(.05,.25,.3,.4);
   di->Draw();

   auto cr = new TCrown(.5,.5,.1,.15);
   cr->SetFillColor(19);
   cr->Draw();

   for (int i=0; i<10000; i++) {
      double x = gRandom->Rndm();
      double y = gRandom->Rndm();
      auto p   = new TMarker(x,y,7);
      p->Draw();
      if (el->IsInside(x,y) || bx->IsInside(x,y) ||
          pv->IsInside(x,y) || di->IsInside(x,y) ||
          cr->IsInside(x,y) || gr->IsInside(x,y)) {
         p->SetMarkerColor(kGreen);
      } else {
         p->SetMarkerColor(kRed);
      }
   }
}

1 Like