Skip to content

Commit

Permalink
implement missing IsInside() (root-project#15074)
Browse files Browse the repository at this point in the history
* implement missing IsInside()

* Add missing `<CR>`s

* clang format

* More clang format

* Final adjustment
  • Loading branch information
couet authored Apr 2, 2024
1 parent ef6b35e commit 845a003
Show file tree
Hide file tree
Showing 7 changed files with 169 additions and 29 deletions.
3 changes: 2 additions & 1 deletion graf2d/graf/inc/TCrown.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,12 @@ class TCrown : public TEllipse {
TCrown(const TCrown &crown);
~TCrown() override;

void Copy(TObject &crown) const override;
void Copy(TObject &crown) const override;
Int_t DistancetoPrimitive(Int_t px, Int_t py) override;
virtual TCrown *DrawCrown(Double_t x1, Double_t y1, Double_t radin, Double_t radout,
Double_t phimin=0, Double_t phimax=360, Option_t *option="");
void ExecuteEvent(Int_t event, Int_t px, Int_t py) override;
Int_t IsInside(Double_t x, Double_t y) const;
void Paint(Option_t *option="") override;
void SavePrimitive(std::ostream &out, Option_t *option = "") override;

Expand Down
2 changes: 1 addition & 1 deletion graf2d/graf/inc/TDiamond.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class TDiamond : public TPaveText {
~TDiamond() override;
Int_t DistancetoPrimitive(Int_t px, Int_t py) override;
void Draw(Option_t *option="") override;
Int_t IsInside(Double_t x, Double_t y) const override;
void ExecuteEvent(Int_t event, Int_t px, Int_t py) override;
void Paint(Option_t *option="") override;
void SavePrimitive(std::ostream &out, Option_t *option = "") override;
Expand All @@ -31,4 +32,3 @@ class TDiamond : public TPaveText {
};

#endif

1 change: 1 addition & 0 deletions graf2d/graf/inc/TEllipse.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ class TEllipse : public TObject, public TAttLine, public TAttFill, public TAttBB
void Draw(Option_t *option="") override;
virtual TEllipse *DrawEllipse(Double_t x1, Double_t y1, Double_t r1,Double_t r2,Double_t phimin, Double_t phimax,Double_t theta,Option_t *option="");
void ExecuteEvent(Int_t event, Int_t px, Int_t py) override;
Int_t IsInside(Double_t x, Double_t y) const;
Double_t GetX1() const {return fX1;}
Double_t GetY1() const {return fY1;}
Double_t GetR1() const {return fR1;}
Expand Down
91 changes: 65 additions & 26 deletions graf2d/graf/src/TCrown.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,45 @@ void TCrown::ExecuteEvent(Int_t event, Int_t px, Int_t py)
TEllipse::ExecuteEvent(event,px,py);
}

////////////////////////////////////////////////////////////////////////////////
/// Return 1 if the point (x,y) is inside the polygon defined by
/// the crown 0 otherwise.

Int_t TCrown::IsInside(Double_t x, Double_t y) const
{

const Double_t kPI = TMath::Pi();
const Int_t np = 40;
static Double_t xc[2 * np + 3], yc[2 * np +3];

Double_t angle, dx, dy;
Double_t dphi = (fPhimax - fPhimin) * kPI / (180 * np);
Double_t ct = TMath::Cos(kPI * fTheta / 180);
Double_t st = TMath::Sin(kPI * fTheta / 180);
Int_t i;

// compute outer points
for (i = 0; i <= np; i++) {
angle = fPhimin * kPI / 180 + Double_t(i) * dphi;
dx = fR2 * TMath::Cos(angle);
dy = fR2 * TMath::Sin(angle);
xc[i] = fX1 + dx * ct - dy * st;
yc[i] = fY1 + dx * st + dy * ct;
}
// compute inner points
for (i = 0; i <= np; i++) {
angle = fPhimin * kPI / 180 + Double_t(i) * dphi;
dx = fR1 * TMath::Cos(angle);
dy = fR1 * TMath::Sin(angle);
xc[2 * np - i + 1] = fX1 + dx * ct - dy * st;
yc[2 * np - i + 1] = fY1 + dx * st + dy * ct;
}
xc[2 * np + 2] = xc[0];
yc[2 * np + 2] = yc[0];

return (Int_t)TMath::IsInside(x, y, 2 * np + 3, xc, yc);
}

////////////////////////////////////////////////////////////////////////////////
/// Paint this crown with its current attributes.

Expand All @@ -182,47 +221,47 @@ void TCrown::Paint(Option_t *)

const Double_t kPI = TMath::Pi();
const Int_t np = 40;
static Double_t x[2*np+3], y[2*np+3];
static Double_t x[2 * np + 3], y[2 * np + 3];
TAttLine::Modify();
TAttFill::Modify();

Double_t angle,dx,dy;
Double_t dphi = (fPhimax-fPhimin)*kPI/(180*np);
Double_t ct = TMath::Cos(kPI*fTheta/180);
Double_t st = TMath::Sin(kPI*fTheta/180);
Double_t dphi = (fPhimax - fPhimin) * kPI / (180 * np);
Double_t ct = TMath::Cos(kPI * fTheta / 180);
Double_t st = TMath::Sin(kPI * fTheta / 180);
Int_t i;
//compute outer points
for (i=0;i<=np;i++) {
angle = fPhimin*kPI/180 + Double_t(i)*dphi;
dx = fR2*TMath::Cos(angle);
dy = fR2*TMath::Sin(angle);
x[i] = fX1 + dx*ct - dy*st;
y[i] = fY1 + dx*st + dy*ct;
// compute outer points
for (i = 0; i <= np; i++) {
angle = fPhimin * kPI / 180 + Double_t(i) * dphi;
dx = fR2 * TMath::Cos(angle);
dy = fR2 * TMath::Sin(angle);
x[i] = fX1 + dx * ct - dy * st;
y[i] = fY1 + dx * st + dy * ct;
}
//compute inner points
for (i=0;i<=np;i++) {
angle = fPhimin*kPI/180 + Double_t(i)*dphi;
dx = fR1*TMath::Cos(angle);
dy = fR1*TMath::Sin(angle);
x[2*np-i+1] = fX1 + dx*ct - dy*st;
y[2*np-i+1] = fY1 + dx*st + dy*ct;
// compute inner points
for (i = 0; i <= np; i++) {
angle = fPhimin * kPI / 180 + Double_t(i) * dphi;
dx = fR1 * TMath::Cos(angle);
dy = fR1 * TMath::Sin(angle);
x[2 * np - i + 1] = fX1 + dx * ct - dy * st;
y[2 * np - i + 1] = fY1 + dx * st + dy * ct;
}
x[2*np+2] = x[0];
y[2*np+2] = y[0];
if (fPhimax-fPhimin >= 360 ) {
x[2 * np + 2] = x[0];
y[2 * np + 2] = y[0];
if (fPhimax - fPhimin >= 360 ) {
// a complete filled crown
if (GetFillColor() && GetFillStyle()) {
gPad->PaintFillArea(2*np+2,x,y);
gPad->PaintFillArea(2 * np + 2,x,y);
}
// a complete empty crown
if (GetLineStyle()) {
gPad->PaintPolyLine(np+1,x,y);
gPad->PaintPolyLine(np+1,&x[np+1],&y[np+1]);
gPad->PaintPolyLine(np + 1,x,y);
gPad->PaintPolyLine(np + 1,&x[np + 1],&y[np + 1]);
}
} else {
//crown segment
if (GetFillColor() && GetFillStyle()) gPad->PaintFillArea(2*np+2,x,y);
if (GetLineStyle()) gPad->PaintPolyLine(2*np+3,x,y);
if (GetFillColor() && GetFillStyle()) gPad->PaintFillArea(2 * np + 2,x,y);
if (GetLineStyle()) gPad->PaintPolyLine(2 * np + 3,x,y);
}
}

Expand Down
21 changes: 21 additions & 0 deletions graf2d/graf/src/TDiamond.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,27 @@ void TDiamond::ExecuteEvent(Int_t event, Int_t px, Int_t py)
}
}

////////////////////////////////////////////////////////////////////////////////
/// Return 1 if the point (x,y) is inside the polygon defined by
/// the diamond 0 otherwise.

Int_t TDiamond::IsInside(Double_t x, Double_t y) const
{

Double_t xd[4], yd[4];

xd[0] = fX1;
yd[0] = (fY2 + fY1) / 2.;
xd[1] = (fX2 + fX1) / 2.;
yd[1] = fY1;
xd[2] = fX2;
yd[2] = yd[0];
xd[3] = xd[1];
yd[3] = fY2;

return (Int_t)TMath::IsInside(x, y, 4, xd, yd);
}

////////////////////////////////////////////////////////////////////////////////
/// Paint this diamond with its current attributes.

Expand Down
34 changes: 33 additions & 1 deletion graf2d/graf/src/TEllipse.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
#include "TVirtualX.h"


const Double_t kPI = 3.14159265358979323846;
constexpr Double_t kPI = TMath::Pi();

ClassImp(TEllipse);

Expand Down Expand Up @@ -507,6 +507,38 @@ void TEllipse::ExecuteEvent(Int_t event, Int_t px, Int_t py)
}
}

////////////////////////////////////////////////////////////////////////////////
/// Return 1 if the point (x,y) is inside the polygon defined by
/// the ellipse 0 otherwise.
/// Author: Ole Hansen ([email protected])
Int_t TEllipse::IsInside(Double_t x, Double_t y) const
{
x -= fX1;
y -= fY1;
Double_t th = fTheta * TMath::DegToRad();
Double_t st = TMath::Sin(th);
Double_t ct = TMath::Cos(th);
Double_t xx = ct * x + st * y;
Double_t yy = -st * x + ct * y;

if (TMath::Abs(xx) > fR1 || TMath::Abs(yy) > fR2)
return 0;
Double_t xn = xx / fR1;
Double_t yn = yy / fR2;
if (xn * xn + yn * yn > 1.)
return 0;
if (fPhimax - fPhimin >= 360.)
return 1;
Double_t phimin = std::fmod(fPhimin, 360.);
Double_t phimax = std::fmod(fPhimax, 360.);
Double_t phi = TMath::RadToDeg()*(TMath::Pi() + TMath::ATan2(-yy * fR1 / fR2, -xx));
if (phi < phimin || phi > phimax)
return 0;

return 1;
}


////////////////////////////////////////////////////////////////////////////////
/// List this ellipse with its attributes.

Expand Down
46 changes: 46 additions & 0 deletions tutorials/graphics/inside.C
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/// \file
/// \ingroup tutorial_graphics
/// \notebook -js
/// Test the IsInside methods of various graphics primitives.
///
/// \macro_image
/// \macro_code
///
/// \author Olivier Couet

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);
}
}
}

0 comments on commit 845a003

Please sign in to comment.