Re: [ROOT] Bug in TEllipse::DistancetoPrimitive

From: Rene Brun (Rene.Brun@cern.ch)
Date: Fri Mar 23 2001 - 18:15:12 MET


Hi Brett,

I have implemented your algorithm with some changes.
In particular, if the ellipse is not filled, the function must return
OK only if the mouse is on the ellipse outline.

Thanks for this contribution and also to remind me to set some default
values for the ellipse parameters in the default constructor.
New version now in CVS.

Rene Brun

Brett Viren wrote:
> 
> Hi,
> 
> I guess I found a bug in TEllipse::DistancetoPrimitive (v3.00/06 from
> CVS of a week ago or so) It does not seem to correctly calculate what
> it should.  I can't quite figure out what it is trying to do, but it
> does fail to return the correct determination of whether the pointer
> is inside or outside the ellipse.  This is only noticeable on
> non-circular ellipses.
> 
> See appended code (particularly method MyThing::DistancetoPrimitive)
> for a test case and possible fix.  Compile w/ and w/out -DUSE_TELLIPSE
> to get the two different versions.  When compiling with
> -DUSE_TELLIPSE, squash the ellipse first to see the bug.
> 
> Regards,
> -Brett.
> 
> //////////////////////////////////////////////
> // drawstuff.cxx - simple ROOT drawing example
> // to compile:
> // g++ -g -Wall -O -o drawstuff drawstuff.cxx `root-config --cflags --glibs`
> //
> #include "TROOT.h"
> #include "TApplication.h"
> #include "TCanvas.h"
> #include "TEllipse.h"
> 
> #include <iostream>
> 
> class MyThing: public TObject
> {
>     TEllipse fEllipse;
> public:
>     MyThing();
>     void Draw(Option_t* opt);
>     void Paint(Option_t* opt);
>     Int_t DistancetoPrimitive(Int_t px, Int_t py);
>     void ExecuteEvent(Int_t event, Int_t px, Int_t py);
> };
> 
> MyThing::MyThing()
>     : TObject(),
>       fEllipse(10.0,20.0,2.0,4.0,0,360,10)
> {
>     fEllipse.SetFillColor(6);
>     fEllipse.SetFillStyle(3008);
>     fEllipse.SetX1(10);
>     fEllipse.SetY1(10);
>     fEllipse.SetR1(9);
>     fEllipse.SetR2(1);
> }
> Int_t MyThing::DistancetoPrimitive(Int_t px, Int_t py)
> {
>     Int_t dist;
> //#define USE_TELLIPSE
> #ifdef USE_TELLIPSE
>     dist = fEllipse.DistancetoPrimitive(px,py);
> #else
> 
>     Double_t x = gPad->AbsPixeltoX(px);
>     Double_t y = gPad->AbsPixeltoY(py);
> 
>     Double_t dxnr = x - fEllipse.GetX1();
>     Double_t dynr = y - fEllipse.GetY1();
> 
>     Double_t ct = TMath::Cos(M_PI*fEllipse.GetTheta()/180.0);
>     Double_t st = TMath::Sin(M_PI*fEllipse.GetTheta()/180.0);
> 
>     Double_t dx = dxnr*ct + dynr*st;
>     Double_t dy = - dxnr*st + dynr*ct;
> 
>     Double_t r1 = fEllipse.GetR1();
>     Double_t r2 = fEllipse.GetR2();
> 
>     Double_t distp = TMath::Sqrt(dx*dx + dy*dy);
> 
>     Double_t tana = dy/dx;
>     tana *= tana;
>     Double_t distr = sqrt((1+tana)/(1.0/(r1*r1) + tana/(r2*r2)));
>     if (distr > distp) dist = 0;
>     else dist = 9999;
> 
> #endif
>     return dist;
> }
> void MyThing::ExecuteEvent(Int_t event, Int_t px, Int_t py)
> {
>     fEllipse.ExecuteEvent(event,px,py);
> }
> void MyThing::Draw(Option_t* opt)
> {
>     this->AppendPad();
> }
> void MyThing::Paint(Option_t* opt)
> {
>     fEllipse.Paint();
> }
> int main (int argc, char *argv[])
> {
>     TROOT blah("blah", "blah");
>     TApplication app("blah", &argc, argv, 0, 0);
>     TCanvas c;
>     TPad p("blah","blah",0.0,0.0,1.0,1.0);
>     p.Range(0.0,0.0,20.0,20.0);
>     c.cd();
>     p.Draw();
> 
>     p.cd();
>     MyThing mt;
>     mt.Draw("");
> 
>     c.Update();
>     app.Run();
>     return 0;
> } // end of main()



This archive was generated by hypermail 2b29 : Tue Jan 01 2002 - 17:50:40 MET