00001
00002
00003
00004
00005
00007
00008 #include <fstream>
00009 #include "TObjArray.h"
00010 #include "TRandom.h"
00011 #include "TMatrix.h"
00012 #include "TMath.h"
00013 #include "TVector2.h"
00014
00015 #include "BField/TIntList.h"
00016
00017
00018
00019
00020 #include "BField/BFLWingedEdge.h"
00021 #include "BField/BFLVorOperator.h"
00022 #include "BField/BFLVoronoiMaker.h"
00023
00024 ClassImp(BFLVorOperator)
00025
00026
00027
00028
00030
00031 BFLVorOperator::BFLVorOperator(BFLWingedEdge * voronoi)
00032 {
00033
00034 fVor = (BFLWingedEdge *) voronoi;
00035 fInVtxCache = new TIntList();
00036 fOutVtxCache = new TIntList();
00037 }
00039
00040 BFLVorOperator::~BFLVorOperator()
00041 {
00042 delete fInVtxCache;
00043 delete fOutVtxCache;
00044 }
00046
00047 TIntList * BFLVorOperator::RetrieveEdgesIncidentToVtx(Int_t vtx) const
00048 {
00049
00050
00051
00052
00053 Int_t k, kstart;
00054 TIntList * IncidentEdges = new TIntList();
00055
00056 k = fVor->GetEdgeAroundVtx(vtx);
00057 kstart = k;
00058
00059 do {
00060
00061 IncidentEdges->AddLast(k);
00062 if( vtx == fVor->GetStartVtx(k) ) {
00063 k = fVor->GetCcwPredecessor(k);
00064 } else {
00065 k = fVor->GetCcwSuccessor(k);
00066 }
00067
00068 } while ( k != kstart );
00069
00070 return IncidentEdges;
00071 }
00073
00074 TIntList * BFLVorOperator::RetrievePolygonsIncidentToVtx(Int_t vtx) const
00075 {
00076
00077
00078
00079
00080 Int_t k, kstart, poly;
00081 TIntList * IncidentPolygons = new TIntList();
00082
00083 k = fVor->GetEdgeAroundVtx(vtx);
00084 kstart = k;
00085
00086 do {
00087
00088 if( vtx == fVor->GetStartVtx(k) ) {
00089 poly = fVor->GetLeftPolyg(k);
00090 k = fVor->GetCcwPredecessor(k);
00091 } else {
00092 poly = fVor->GetRightPolyg(k);
00093 k = fVor->GetCcwSuccessor(k);
00094 }
00095 IncidentPolygons -> AddLast(poly);
00096
00097 } while( k != kstart);
00098
00099 return IncidentPolygons;
00100 }
00102
00103 TIntList * BFLVorOperator::RetrieveEdgesSurrPolygon(Int_t poly) const
00104 {
00105 Int_t k, kstart;
00106 TIntList * SurroundingEdges = new TIntList();
00107
00108 k = fVor->GetEdgeAroundPolyg(poly);
00109 kstart = k;
00110
00111 do {
00112
00113 SurroundingEdges->AddLast(k);
00114
00115 if(poly == fVor->GetLeftPolyg(k)){
00116 k = fVor->GetCwSuccessor(k);
00117 } else {
00118 k = fVor->GetCwPredecessor(k);
00119 }
00120 } while( k!=kstart );
00121
00122 return SurroundingEdges;
00123 }
00124
00126
00127 TIntList * BFLVorOperator::RetrieveVtxSurrPolygon(Int_t poly) const
00128 {
00129 Int_t k, kstart;
00130 TIntList * SurrVertices = new TIntList();
00131
00132 k = fVor->GetEdgeAroundPolyg(poly);
00133 kstart = k;
00134
00135 do {
00136
00137 if(poly == fVor->GetLeftPolyg(k)){
00138 SurrVertices->AddLast(fVor->GetEndVtx(k));
00139 k = fVor->GetCwSuccessor(k);
00140 } else {
00141 SurrVertices->AddLast(fVor->GetStartVtx(k));
00142 k = fVor->GetCwPredecessor(k);
00143 }
00144
00145 } while( k!=kstart );
00146
00147 return SurrVertices;
00148 }
00149
00151
00152 Int_t BFLVorOperator::GetFirstIntersectEdge(void) const
00153 {
00154
00155
00156
00157
00158
00159 Int_t FirstIntersectEdgeID = 0;
00160 TIntList * IntersectEdges = new TIntList();
00161
00162
00163 TIntList * PolyEdgeIDs = RetrieveEdgesSurrPolygon(fCurrentPolygID);
00164
00165
00166
00167 for(Int_t i=0; i<PolyEdgeIDs->NumberOfElements(); i++){
00168 Int_t iedge = PolyEdgeIDs->At(i);
00169 if(EdgeHasNewVtx(iedge)) IntersectEdges->Add(iedge);
00170 }
00171
00172 if(IntersectEdges->NumberOfElements() != 2) {
00173 delete PolyEdgeIDs;
00174 delete IntersectEdges;
00175 return -1;
00176 }
00177
00178
00179
00180
00181
00182 BFLNode VtxOnFirstEdge = FindNewVtx(IntersectEdges->At(0));
00183 BFLNode VtxOnSecondEdge = FindNewVtx(IntersectEdges->At(1));
00184
00185 if(Clockwise(fCurrentGen,&VtxOnFirstEdge,&VtxOnSecondEdge) == -1) {
00186 FirstIntersectEdgeID = IntersectEdges->At(0);
00187 } else FirstIntersectEdgeID = IntersectEdges->At(1);
00188
00189
00190 delete PolyEdgeIDs;
00191 delete IntersectEdges;
00192
00193 return FirstIntersectEdgeID;
00194 }
00196
00197 Int_t BFLVorOperator::Clockwise(BFLNode * nA, BFLNode * nB,
00198 BFLNode * nC) const
00199 {
00200
00201
00202
00203
00204
00205
00206
00207
00208 Int_t cwise;
00209 Float_t dxa, dya, dxb, dyb;
00210
00211 dxa = ( nB->GetX() ) - ( nA->GetX() );
00212 dxb = ( nC->GetX() ) - ( nA->GetX() );
00213 dya = ( nB->GetY() ) - ( nA->GetY() );
00214 dyb = ( nC->GetY() ) - ( nA->GetY() );
00215
00216 if (dxa*dyb > dya*dxb) cwise = -1;
00217 else if (dxa*dyb < dya*dxb) cwise = 1;
00218 else {
00219 if (dxa*dxb < 0 || dya*dyb < 0 ) cwise = -1;
00220 else if (dxa*dxa + dya*dya >= dxb*dxb + dyb*dyb) cwise = 0;
00221 else cwise = 1;
00222 }
00223
00224 return cwise;
00225 }
00227
00228 Int_t BFLVorOperator::GetNextIntersectEdge(Int_t PrEdgeID) const
00229 {
00230
00231
00232
00233
00234
00235
00236 Int_t NextEdgeID = 0, iedge;
00237 TIntList * PolyEdgeIDs;
00238
00239
00240 PolyEdgeIDs = RetrieveEdgesSurrPolygon(fCurrentPolygID);
00241
00242
00243 PolyEdgeIDs->Remove(PrEdgeID);
00244
00245
00246 for(Int_t i = 0; i < PolyEdgeIDs->NumberOfElements(); i++){
00247 iedge = PolyEdgeIDs->At(i);
00248 if(EdgeHasNewVtx(iedge)) NextEdgeID = iedge;
00249 }
00250
00251 delete PolyEdgeIDs;
00252
00253 return NextEdgeID;
00254 }
00256
00257 Bool_t BFLVorOperator::EdgeHasNewVtx(Int_t EdgeID) const
00258 {
00259
00260
00261
00262
00263
00264 Int_t SVtxID, EVtxID;
00265 Bool_t SVtxIsInside, EVtxIsInside, HasNewVtx;
00266
00267
00268 SVtxID = fVor->GetStartVtx(EdgeID);
00269 EVtxID = fVor->GetEndVtx(EdgeID);
00270
00271
00272
00273 SVtxIsInside = VtxIsInsideNewPolyg(SVtxID);
00274 EVtxIsInside = VtxIsInsideNewPolyg(EVtxID);
00275
00276
00277 if((SVtxIsInside && !EVtxIsInside)||(!SVtxIsInside && EVtxIsInside)){
00278 HasNewVtx = kTRUE;
00279 } else {
00280 HasNewVtx = kFALSE;
00281 }
00282
00283 return HasNewVtx;
00284 }
00286
00287 Bool_t BFLVorOperator::EdgeIsInsideNewPolygon(Int_t EdgeID) const
00288 {
00289
00290
00291
00292
00293 Int_t SVtxID, EVtxID;
00294 Bool_t SVtxIsInside, EVtxIsInside, IsInside;
00295
00296
00297 SVtxID = fVor->GetStartVtx(EdgeID);
00298 EVtxID = fVor->GetEndVtx(EdgeID);
00299
00300
00301
00302 SVtxIsInside = VtxIsInsideNewPolyg(SVtxID);
00303 EVtxIsInside = VtxIsInsideNewPolyg(EVtxID);
00304
00305
00306
00307 if(SVtxIsInside && EVtxIsInside) IsInside = kTRUE;
00308 else IsInside = kFALSE;
00309
00310 return IsInside;
00311 }
00313
00314 void BFLVorOperator::ResetVtxCache(void)
00315 {
00316 fInVtxCache->Delete();
00317 fOutVtxCache->Delete();
00318 }
00320
00321 Bool_t BFLVorOperator::VtxIsInsideNewPolyg(Int_t VtxID) const
00322 {
00323
00324
00325
00326 Bool_t IsInside;
00327
00328
00329 if (fInVtxCache->Exists(VtxID)) return kTRUE;
00330 else if (fOutVtxCache->Exists(VtxID)) return kFALSE;
00331 else {
00332 if (fVor->GetWeight(VtxID)) {
00333
00334 TIntList * PolygsAround;
00335 TObjArray * PointsOnCircle = new TObjArray(3);
00336
00337
00338
00339 PolygsAround = RetrievePolygonsIncidentToVtx(VtxID);
00340
00341
00342 for(Int_t i=0; i < PolygsAround->NumberOfElements(); i++) {
00343 Int_t GenID = fVor->PolygonToGenerator(PolygsAround->At(i));
00344 Float_t x = fVor->GetGeneratorX(GenID);
00345 Float_t y = fVor->GetGeneratorY(GenID);
00346 PointsOnCircle->Add(new BFLNode(x,y));
00347 }
00348
00349
00350
00351 if (IsInTheCircle(PointsOnCircle,fCurrentGen) == 1) {
00352 IsInside = kTRUE;
00353 fInVtxCache->AddLast(VtxID);
00354 } else {
00355 IsInside = kFALSE;
00356 fOutVtxCache->AddLast(VtxID);
00357 }
00358
00359
00360 delete PolygsAround;
00361 PointsOnCircle->Delete();
00362 delete PointsOnCircle;
00363
00364 } else {
00365 IsInside = kFALSE;
00366 fOutVtxCache->AddLast(VtxID);
00367 }
00368 }
00369
00370 return IsInside;
00371 }
00372
00374
00375 Int_t BFLVorOperator::IsInTheCircle(TObjArray * PointsOnCircle,
00376 BFLNode * point) const
00377 {
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394 Int_t irow, InCircle;
00395 Double_t det;
00396 BFLNode * PointOnCircle;
00397
00398 TMatrix H = TMatrix(4,4);
00399
00400
00401 for(irow=0; irow<H.GetNrows(); irow++) H(irow,0) = 1;
00402
00403 TIter next(PointsOnCircle);
00404 irow = 0;
00405 while( (PointOnCircle = (BFLNode *)next())) {
00406 H(irow,1) = PointOnCircle->GetX();
00407 H(irow,2) = PointOnCircle->GetY();
00408
00409
00410 H(irow,3) = PointOnCircle->GetX()*PointOnCircle->GetX() +
00411 PointOnCircle->GetY()*PointOnCircle->GetY();
00412 irow++;
00413 }
00414
00415
00416 H(3,1) = point->GetX();
00417 H(3,2) = point->GetY();
00418
00419
00420 H(3,3) = point->GetX()*point->GetX() + point->GetY()*point->GetY();
00421
00422
00423 det = H.Determinant();
00424
00425 if (det == 0) InCircle = 0;
00426 else if (det > 0) InCircle = -1;
00427 else InCircle = 1;
00428
00429
00430 delete PointOnCircle;
00431
00432 return InCircle;
00433 }
00435
00436 BFLNode BFLVorOperator::VtxPosition(TObjArray * PointsOnCircle) const
00437 {
00438
00439
00440
00441
00442
00443
00444
00445 Int_t i=0;
00446 Float_t A, B, C, Xvtx, Yvtx;
00447 Float_t x[3], y[3], r[3];
00448 BFLNode * PointOnCircle;
00449
00450 TIter next(PointsOnCircle);
00451 while( (PointOnCircle = (BFLNode *)next())) {
00452 x[i]=PointOnCircle->GetX();
00453 y[i]=PointOnCircle->GetY();
00454
00455 r[i]=x[i]*x[i] + y[i]*y[i];
00456 i++;
00457 }
00458
00459 A = x[1]*y[2] - x[2]*y[1] - x[0]*y[2] +
00460 x[2]*y[0] + x[0]*y[1] - x[1]*y[0];
00461
00462 B = y[1]*r[2] - y[2]*r[1] - y[0]*r[2] +
00463 y[2]*r[0] + y[0]*r[1] - y[1]*r[0];
00464
00465 C = - x[0]*r[1] - x[1]*r[2] - x[2]*r[0] +
00466 x[0]*r[2] + x[1]*r[0] + x[2]*r[1];
00467
00468 if(A !=0 ) {
00469 Xvtx = -B/(2*A);
00470 Yvtx = -C/(2*A);
00471 return BFLNode(Xvtx,Yvtx);
00472 } else {
00473 return BFLNode(0.,0.);
00474 }
00475 }
00477
00478 BFLNode BFLVorOperator::FindNewVtx(Int_t EdgeID) const
00479 {
00480
00481
00482
00483
00484
00485 Int_t LeftPolygID, RightPolygID;
00486 Int_t LeftPolygGenID, RightPolygGenID;
00487 Float_t x,y;
00488 BFLNode vtx;
00489 TObjArray * PointsOnCircle = new TObjArray(3);
00490
00491
00492 LeftPolygID = fVor->GetLeftPolyg(EdgeID);
00493 RightPolygID = fVor->GetRightPolyg(EdgeID);
00494
00495
00496 LeftPolygGenID = fVor->GeneratorToPolygon(LeftPolygID);
00497 RightPolygGenID = fVor->GeneratorToPolygon(RightPolygID);
00498
00499
00500
00501 x = fVor->GetGeneratorX(LeftPolygGenID);
00502 y = fVor->GetGeneratorY(LeftPolygGenID);
00503 PointsOnCircle->Add(new BFLNode(x,y));
00504
00505 x = fVor->GetGeneratorX(RightPolygGenID);
00506 y = fVor->GetGeneratorY(RightPolygGenID);
00507 PointsOnCircle->Add(new BFLNode(x,y));
00508
00509 x = fCurrentGen->GetX();
00510 y = fCurrentGen->GetY();
00511 PointsOnCircle->Add(new BFLNode(x,y));
00512
00513 vtx = VtxPosition(PointsOnCircle);
00514
00515
00516 PointsOnCircle->Delete();
00517 delete PointsOnCircle;
00518
00519 return vtx;
00520 }
00522
00523 Float_t BFLVorOperator::GeneratorsDist(Int_t igen, Int_t jgen) const
00524 {
00525
00526
00527 Float_t x = fVor->GetGeneratorX(igen) - fVor->GetGeneratorX(jgen);
00528 Float_t y = fVor->GetGeneratorY(igen) - fVor->GetGeneratorY(jgen);
00529 return TMath::Sqrt(
00530
00531
00532
00533
00534 x*x + y*y);
00535 }
00537
00538 Float_t BFLVorOperator::DistanceFrom(Int_t igen) const
00539 {
00540
00541
00542
00543 Float_t x = fVor->GetGeneratorX(igen) - fCurrentGen->GetX();
00544 Float_t y = fVor->GetGeneratorY(igen) - fCurrentGen->GetY();
00545 return TMath::Sqrt(
00546
00547
00548 x*x + y*y);
00549 }
00551
00552 Int_t BFLVorOperator::MoveToNextPolygon(Int_t PolygID, Int_t EdgeID) const
00553 {
00554
00555
00556
00557 Int_t LeftPolygID, RightPolygID, NextPolygID;
00558
00559 LeftPolygID = fVor->GetLeftPolyg(EdgeID);
00560 RightPolygID = fVor->GetRightPolyg(EdgeID);
00561
00562 if(LeftPolygID != PolygID) NextPolygID = LeftPolygID;
00563 else NextPolygID = RightPolygID;
00564
00565 return NextPolygID;
00566 }
00568
00569 Int_t BFLVorOperator::FindCurrentPolygon(Int_t GuessedPolygID) const
00570 {
00571
00572
00573
00574
00575
00576
00577
00578 Int_t i, NearestGenID, Nedges, AdjacentPolygonID;
00579 Int_t PolygID, EdgeID, AdjGen;
00580 Bool_t IsNearest;
00581 Float_t Dist, DistMin;
00582 TIntList * SurroundingEdges;
00583
00584
00585 if(GuessedPolygID != -1 ) NearestGenID = GuessedPolygID;
00586 else NearestGenID = 1;
00587
00588
00589 DistMin = DistanceFrom(NearestGenID);
00590
00591
00592 do {
00593 IsNearest = kTRUE;
00594
00595
00596 PolygID = fVor->GeneratorToPolygon(NearestGenID);
00597
00598
00599
00600
00601 SurroundingEdges = RetrieveEdgesSurrPolygon(PolygID);
00602
00603
00604
00605 Nedges = SurroundingEdges -> NumberOfElements();
00606 for(i=0; i<Nedges; i++) {
00607
00608
00609 EdgeID = SurroundingEdges -> At(i);
00610 AdjacentPolygonID = MoveToNextPolygon(PolygID,EdgeID);
00611
00612 if(AdjacentPolygonID !=0 ) {
00613
00614
00615 AdjGen = fVor->PolygonToGenerator(AdjacentPolygonID);
00616
00617
00618
00619
00620 Dist = DistanceFrom(AdjGen);
00621
00622
00623 if ( Dist < DistMin - 0.0001) {
00624 DistMin = Dist;
00625 NearestGenID = AdjGen;
00626 IsNearest = kFALSE;
00627 }
00628 }
00629 }
00630
00631
00632 delete SurroundingEdges;
00633
00634 } while(!IsNearest);
00635
00636 return fVor->GeneratorToPolygon(NearestGenID);
00637 }