59 ClassImp(TGeoPolygon);
64 TGeoPolygon::TGeoPolygon()
74 TObject::SetBit(kGeoFinishPolygon, kFALSE);
80 TGeoPolygon::TGeoPolygon(Int_t nvert)
83 Fatal(
"Ctor",
"Invalid number of vertices %i", nvert);
88 fInd =
new Int_t[nvert];
94 TObject::SetBit(kGeoFinishPolygon, kFALSE);
101 TGeoPolygon::~TGeoPolygon()
103 if (fInd)
delete [] fInd;
104 if (fIndc)
delete [] fIndc;
106 fDaughters->Delete();
113 Double_t TGeoPolygon::Area()
const
118 for (ic=0; ic<fNvert; ic++) {
120 j = fInd[(ic+1)%fNvert];
121 area += 0.5*(fX[i]*fY[j]-fX[j]*fY[i]);
123 return TMath::Abs(area);
129 Bool_t TGeoPolygon::Contains(
const Double_t *point)
const
133 for (i=0; i<fNconvex; i++)
134 if (!IsRightSided(point, fIndc[i], fIndc[(i+1)%fNconvex]))
return kFALSE;
135 if (!fDaughters)
return kTRUE;
136 Int_t nd = fDaughters->GetEntriesFast();
137 for (i=0; i<nd; i++) {
138 poly = (TGeoPolygon*)fDaughters->UncheckedAt(i);
139 if (poly->Contains(point))
return kFALSE;
147 void TGeoPolygon::ConvexCheck()
155 for (Int_t i=0; i<fNvert; i++) {
158 point[0] = fX[fInd[k]];
159 point[1] = fY[fInd[k]];
160 if (!IsRightSided(point, fInd[i], fInd[j]))
return;
168 void TGeoPolygon::Draw(Option_t *)
170 if (!gGeoManager)
return;
171 gGeoManager->GetGeomPainter()->DrawPolygon(
this);
178 void TGeoPolygon::FinishPolygon()
180 TObject::SetBit(kGeoFinishPolygon);
187 memcpy(fIndc, fInd, fNvert*
sizeof(Int_t));
192 if (IsConvex())
return;
194 if (!fDaughters) fDaughters =
new TObjArray();
195 TGeoPolygon *poly = 0;
197 Int_t indnext, indback;
199 while (indconv < fNconvex) {
200 indnext = (indconv+1)%fNconvex;
201 nskip = fIndc[indnext]-fIndc[indconv];
202 if (nskip<0) nskip+=fNvert;
208 poly =
new TGeoPolygon(nskip+1);
210 poly->SetNextIndex(fInd[fIndc[indconv]]);
211 poly->SetNextIndex(fInd[fIndc[indnext]]);
212 indback = fIndc[indnext]-1;
213 if (indback < 0) indback+=fNvert;
214 while (indback != fIndc[indconv]) {
215 poly->SetNextIndex(fInd[indback]);
217 if (indback < 0) indback+=fNvert;
219 poly->FinishPolygon();
220 fDaughters->Add(poly);
223 for (indconv=0; indconv<fNconvex; indconv++) fIndc[indconv] = fInd[fIndc[indconv]];
229 void TGeoPolygon::GetVertices(Double_t *x, Double_t *y)
const
231 memcpy(x, fX, fNvert*
sizeof(Double_t));
232 memcpy(y, fY, fNvert*
sizeof(Double_t));
238 void TGeoPolygon::GetConvexVertices(Double_t *x, Double_t *y)
const
240 for (Int_t ic=0; ic<fNconvex; ic++) {
241 x[ic] = fX[fIndc[ic]];
242 y[ic] = fY[fIndc[ic]];
249 Bool_t TGeoPolygon::IsRightSided(
const Double_t *point, Int_t ind1, Int_t ind2)
const
251 Double_t dot = (point[0]-fX[ind1])*(fY[ind2]-fY[ind1]) -
252 (point[1]-fY[ind1])*(fX[ind2]-fX[ind1]);
253 if (!IsClockwise()) dot = -dot;
254 if (dot<-1.E-10)
return kFALSE;
261 Bool_t TGeoPolygon::IsSegConvex(Int_t i1, Int_t i2)
const
263 if (i2<0) i2=(i1+1)%fNvert;
265 for (Int_t i=0; i<fNvert; i++) {
266 if (i==i1 || i==i2)
continue;
267 point[0] = fX[fInd[i]];
268 point[1] = fY[fInd[i]];
269 if (!IsRightSided(point, fInd[i1], fInd[i2]))
return kFALSE;
277 Bool_t TGeoPolygon::IsIllegalCheck()
const
279 if (fNvert<4)
return kFALSE;
280 Bool_t is_illegal = kFALSE;
281 Double_t x1,y1,x2,y2,x3,y3,x4,y4;
282 for (Int_t i=0; i<fNvert-2; i++) {
284 for (Int_t j=i+2; j<fNvert; j++) {
286 if (i==0 && j==(fNvert-1))
continue;
293 x4 = fX[(j+1)%fNvert];
294 y4 = fY[(j+1)%fNvert];
295 if (TGeoShape::IsSegCrossing(x1,y1,x2,y2,x3,y3,x4,y4)) {
296 Error(
"IsIllegalCheck",
"Illegal crossing of segment %d vs. segment %d", i,j);
307 void TGeoPolygon::OutscribedConvex()
313 Int_t *indconv =
new Int_t[fNvert];
314 memset(indconv, 0, fNvert*
sizeof(Int_t));
315 while (iseg<fNvert) {
316 if (!IsSegConvex(iseg)) {
317 if (iseg+2 > fNvert)
break;
318 ivnew = (iseg+2)%fNvert;
322 if (IsSegConvex(iseg, ivnew)) {
326 ivnew = (ivnew+1)%fNvert;
334 ivnew = (iseg+1)%fNvert;
337 if (!fNconvex) indconv[fNconvex++] = iseg;
338 else if (indconv[fNconvex-1] != iseg) indconv[fNconvex++] = iseg;
339 if (iseg<fNvert-1) indconv[fNconvex++] = ivnew;
340 if (ivnew<iseg)
break;
345 Fatal(
"OutscribedConvex",
"cannot build outscribed convex");
348 fIndc =
new Int_t[fNvert];
349 memcpy(fIndc, indconv, fNconvex*
sizeof(Int_t));
356 Double_t TGeoPolygon::Safety(
const Double_t *point, Int_t &isegment)
const
359 Double_t p1[2], p2[3];
360 Double_t lsq, ssq, dx, dy, dpx, dpy, u;
363 for (i1=0; i1<fNvert; i1++) {
364 if (TGeoShape::IsSameWithinTolerance(safe,0)) {
376 dpx = point[0] - p1[0];
377 dpy = point[1] - p1[1];
380 if (TGeoShape::IsSameWithinTolerance(lsq,0)) {
381 ssq = dpx*dpx + dpy*dpy;
388 u = (dpx*dx + dpy*dy)/lsq;
390 dpx = point[0]-p2[0];
391 dpy = point[1]-p2[1];
398 ssq = dpx*dpx + dpy*dpy;
405 safe = TMath::Sqrt(safe);
414 void TGeoPolygon::SetNextIndex(Int_t index)
418 for (i=0; i<fNvert; i++) fInd[i] = i;
421 if (fNconvex >= fNvert) {
422 Error(
"SetNextIndex",
"all indices already set");
425 fInd[fNconvex++] = index;
426 if (fNconvex == fNvert) {
427 if (!fX || !fY)
return;
429 for (i=0; i<fNvert; i++) area += fX[fInd[i]]*fY[fInd[(i+1)%fNvert]]-fX[fInd[(i+1)%fNvert]]*fY[fInd[i]];
430 if (area<0) TObject::SetBit(kGeoACW, kFALSE);
431 else TObject::SetBit(kGeoACW, kTRUE);
438 void TGeoPolygon::SetXY(Double_t *x, Double_t *y)
444 for (i=0; i<fNvert; i++) area += fX[fInd[i]]*fY[fInd[(i+1)%fNvert]]-fX[fInd[(i+1)%fNvert]]*fY[fInd[i]];
445 if (area<0) TObject::SetBit(kGeoACW, kFALSE);
446 else TObject::SetBit(kGeoACW, kTRUE);
448 if (!fDaughters)
return;
450 Int_t nd = fDaughters->GetEntriesFast();
451 for (i=0; i<nd; i++) {
452 poly = (TGeoPolygon*)fDaughters->At(i);
453 if (poly) poly->SetXY(x,y);