TEvePolygonSetProjected.cxx

Go to the documentation of this file.
00001 // @(#)root/eve:$Id: TEvePolygonSetProjected.cxx 37192 2010-12-02 15:54:26Z matevz $
00002 // Authors: Matevz Tadel & Alja Mrak-Tadel: 2006, 2007
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2007, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 #include "TEvePolygonSetProjected.h"
00013 #include "TEveGeoShape.h"
00014 #include "TEveProjectionManager.h"
00015 
00016 #include "TBuffer3D.h"
00017 #include "TBuffer3DTypes.h"
00018 #include "TVirtualPad.h"
00019 #include "TVirtualViewer3D.h"
00020 
00021 namespace
00022 {
00023    struct Seg_t
00024    {
00025       // Helper class for building 2D polygons from TBuffer3D.
00026       Int_t fV1;
00027       Int_t fV2;
00028 
00029       Seg_t(Int_t i1=-1, Int_t i2=-1) : fV1(i1), fV2(i2) {}
00030    };
00031 
00032    typedef std::list<Seg_t>           LSeg_t;
00033    typedef std::list<Seg_t>::iterator LSegIt_t;
00034 }
00035 
00036 
00037 //==============================================================================
00038 //==============================================================================
00039 // TEvePolygonSetProjected
00040 //==============================================================================
00041 
00042 //______________________________________________________________________________
00043 //
00044 // A set of projected polygons.
00045 // Used for storage of projected geometrical shapes.
00046 //
00047 // Internal struct Polygon_t holds only indices into the master vertex
00048 // array in TEvePolygonSetProjected.
00049 
00050 ClassImp(TEvePolygonSetProjected);
00051 
00052 //______________________________________________________________________________
00053 TEvePolygonSetProjected::TEvePolygonSetProjected(const char* n, const char* t) :
00054    TEveShape(n, t),
00055    fBuff(0),
00056    fNPnts(0),
00057    fPnts(0)
00058 {
00059    // Constructor.
00060 }
00061 
00062 //______________________________________________________________________________
00063 TEvePolygonSetProjected::~TEvePolygonSetProjected()
00064 {
00065    // Destructor.
00066 
00067    fPols.clear();
00068    if (fPnts) delete [] fPnts;
00069    if (fBuff) delete fBuff;
00070 }
00071 
00072 //______________________________________________________________________________
00073 void TEvePolygonSetProjected::ComputeBBox()
00074 {
00075    // Override of virtual method from TAttBBox.
00076 
00077    if (fNPnts > 0) {
00078       BBoxInit();
00079       for (Int_t pi = 0; pi < fNPnts; ++pi)
00080          BBoxCheckPoint(fPnts[pi].fX, fPnts[pi].fY, fPnts[pi].fZ);
00081    } else {
00082       BBoxZero();
00083    }
00084 }
00085 
00086 
00087 //==============================================================================
00088 
00089 //______________________________________________________________________________
00090 void TEvePolygonSetProjected::SetProjection(TEveProjectionManager* mng,
00091                                             TEveProjectable* model)
00092 {
00093    // This is virtual method from base-class TEveProjected.
00094 
00095    TEveProjected::SetProjection(mng, model);
00096 
00097    TEveGeoShape* gre = dynamic_cast<TEveGeoShape*>(model);
00098    fBuff = gre->MakeBuffer3D();
00099    CopyVizParams(gre);
00100 }
00101 
00102 //______________________________________________________________________________
00103 void TEvePolygonSetProjected::SetDepthLocal(Float_t d)
00104 {
00105    // Set depth (z-coordinate) of the projected points.
00106 
00107    SetDepthCommon(d, this, fBBox);
00108 
00109    for (Int_t i = 0; i < fNPnts; ++i)
00110       fPnts[i].fZ = fDepth;
00111 }
00112 
00113 //______________________________________________________________________________
00114 void TEvePolygonSetProjected::UpdateProjection()
00115 {
00116    // This is virtual method from base-class TEveProjected.
00117 
00118    if (fBuff == 0) return;
00119 
00120    // drop polygons and projected/reduced points
00121    fPols.clear();
00122    ProjectBuffer3D();
00123 }
00124 
00125 //______________________________________________________________________________
00126 Bool_t TEvePolygonSetProjected::IsFirstIdxHead(Int_t s0, Int_t s1)
00127 {
00128    // Compare the two segments and check if the first index of first segment is starting.
00129 
00130    Int_t v0 = fBuff->fSegs[3*s0 + 1];
00131    Int_t v2 = fBuff->fSegs[3*s1 + 1];
00132    Int_t v3 = fBuff->fSegs[3*s1 + 2];
00133    return v0 != v2 && v0 != v3;
00134 }
00135 
00136 //______________________________________________________________________________
00137 Int_t* TEvePolygonSetProjected::ProjectAndReducePoints()
00138 {
00139    // Project and reduce buffer points.
00140 
00141    TEveProjection* projection = fManager->GetProjection();
00142 
00143    Int_t buffN = fBuff->NbPnts();
00144    TEveVector*  pnts  = new TEveVector[buffN];
00145    for (Int_t i = 0; i < buffN; ++i)
00146    {
00147       pnts[i].Set(fBuff->fPnts[3*i],fBuff->fPnts[3*i+1], fBuff->fPnts[3*i+2]);
00148       projection->ProjectPoint(pnts[i].fX, pnts[i].fY, pnts[i].fZ, 0,
00149                                TEveProjection::kPP_Plane);
00150    }
00151 
00152    if (fPnts) delete [] fPnts;
00153    fNPnts=0;
00154    Int_t *idxMap = new Int_t[buffN];
00155    Int_t *ra     = new Int_t[buffN];  // list of reduced vertices
00156    for (UInt_t v = 0; v < (UInt_t)buffN; ++v)
00157    {
00158       idxMap[v] = -1;
00159       for (Int_t k = 0; k < fNPnts; ++k)
00160       {
00161          if (pnts[v].SquareDistance(pnts[ra[k]]) < TEveProjection::fgEpsSqr)
00162          {
00163             idxMap[v] = k;
00164             break;
00165          }
00166       }
00167       // have not found a point inside epsilon, add new point in scaled array
00168       if (idxMap[v] == -1)
00169       {
00170          idxMap[v] = fNPnts;
00171          ra[fNPnts] = v;
00172          ++fNPnts;
00173       }
00174    }
00175 
00176    // write the array of scaled points
00177    fPnts = new TEveVector[fNPnts];
00178    for (Int_t idx = 0; idx < fNPnts; ++idx)
00179    {
00180       Int_t i = ra[idx];
00181       projection->ProjectPoint(pnts[i].fX, pnts[i].fY, pnts[i].fZ, fDepth,
00182                                TEveProjection::kPP_Distort);
00183       fPnts[idx].Set(pnts[i]);
00184    }
00185    delete [] ra;
00186    delete [] pnts;
00187    // printf("reduced %d points of %d\n", fNPnts, N);
00188 
00189    return idxMap;
00190 }
00191 
00192 //______________________________________________________________________________
00193 Float_t TEvePolygonSetProjected::AddPolygon(std::list<Int_t>& pp, vpPolygon_t& pols)
00194 {
00195    // Check if polygon has dimensions above TEveProjection::fgEps and add it
00196    // to a list if it is not a duplicate.
00197 
00198    if (pp.size() <= 2) return 0;
00199 
00200    Float_t bbox[4] = { 1e6, -1e6, 1e6, -1e6 };
00201    for (std::list<Int_t>::iterator u = pp.begin(); u != pp.end(); ++u)
00202    {
00203       Int_t idx = *u;
00204       if (fPnts[idx].fX < bbox[0]) bbox[0] = fPnts[idx].fX;
00205       if (fPnts[idx].fX > bbox[1]) bbox[1] = fPnts[idx].fX;
00206 
00207       if (fPnts[idx].fY < bbox[2]) bbox[2] = fPnts[idx].fY;
00208       if (fPnts[idx].fY > bbox[3]) bbox[3] = fPnts[idx].fY;
00209    }
00210    Float_t eps = 2*TEveProjection::fgEps;
00211    if ((bbox[1]-bbox[0]) < eps || (bbox[3]-bbox[2]) < eps) return 0;
00212 
00213    // Duplication
00214    for (vpPolygon_i poi = pols.begin(); poi != pols.end(); ++poi)
00215    {
00216       Polygon_t& refP = *poi;
00217 
00218       if ((Int_t) pp.size() != refP.fNPnts)
00219          continue;
00220 
00221       Int_t start_idx = refP.FindPoint(pp.front());
00222       if (start_idx < 0)
00223             continue;
00224       if (++start_idx >= refP.fNPnts) start_idx = 0;
00225       
00226       // Same orientation duplicate
00227       {
00228          std::list<Int_t>::iterator u = ++pp.begin();
00229          Int_t pidx = start_idx;
00230          while (u != pp.end())
00231          {
00232             if ((*u) != refP.fPnts[pidx])
00233                break;
00234             ++u;
00235             if (++pidx >= refP.fNPnts) pidx = 0;
00236          }
00237          if (u == pp.end()) return 0;
00238       }
00239       // Inverse orientation duplicate
00240       {
00241          std::list<Int_t>::iterator u = --pp.end();
00242          Int_t pidx = start_idx;
00243          while (u != pp.begin())
00244          {
00245             if ((*u) != refP.fPnts[pidx])
00246                break;
00247             --u;
00248             if (++pidx >= refP.fNPnts) pidx = 0;
00249          }
00250          if (u == pp.begin()) return 0;
00251       }
00252    }
00253 
00254    Int_t *pv    = new Int_t[pp.size()];
00255    Int_t  count = 0;
00256    for (std::list<Int_t>::iterator u = pp.begin(); u != pp.end(); ++u)
00257    {
00258       pv[count] = *u;
00259       ++count;
00260    }
00261 
00262    pols.push_back(Polygon_t());
00263    pols.back().fNPnts =  pp.size();
00264    pols.back().fPnts  = &pv[0];
00265 
00266    return (bbox[1]-bbox[0]) * (bbox[3]-bbox[2]);
00267 }
00268 
00269 //______________________________________________________________________________
00270 Float_t TEvePolygonSetProjected::MakePolygonsFromBP(Int_t* idxMap)
00271 {
00272    // Build polygons from list of buffer polygons.
00273 
00274    TEveProjection* projection = fManager->GetProjection();
00275    Int_t   *bpols = fBuff->fPols;
00276    Float_t  surf  = 0; // surface of projected polygons
00277    for (UInt_t pi = 0; pi < fBuff->NbPols(); ++pi)
00278    {
00279       std::list<Int_t> pp; // points in current polygon
00280       UInt_t  segN =  bpols[1];
00281       Int_t  *seg  = &bpols[2];
00282       // start idx in the fist segment depends of second segment
00283       Int_t   tail, head;
00284       if (IsFirstIdxHead(seg[0], seg[1]))
00285       {
00286          head = idxMap[fBuff->fSegs[3*seg[0] + 1]];
00287          tail = idxMap[fBuff->fSegs[3*seg[0] + 2]];
00288       }
00289       else
00290       {
00291          head = idxMap[fBuff->fSegs[3*seg[0] + 2]];
00292          tail = idxMap[fBuff->fSegs[3*seg[0] + 1]];
00293       }
00294       pp.push_back(head);
00295       // printf("start idx head %d, tail %d\n", head, tail);
00296       LSeg_t segs;
00297       for (UInt_t s = 1; s < segN; ++s)
00298          segs.push_back(Seg_t(fBuff->fSegs[3*seg[s] + 1],fBuff->fSegs[3*seg[s] + 2]));
00299 
00300       for (LSegIt_t it = segs.begin(); it != segs.end(); ++it)
00301       {
00302          Int_t mv1 = idxMap[(*it).fV1];
00303          Int_t mv2 = idxMap[(*it).fV2];
00304 
00305          if ( ! projection->AcceptSegment(fPnts[mv1], fPnts[mv2], TEveProjection::fgEps))
00306          {
00307             pp.clear();
00308             break;
00309          }
00310          if (tail != pp.back()) pp.push_back(tail);
00311          tail = (mv1 == tail) ? mv2 : mv1;
00312       }
00313 
00314       if ( ! pp.empty())
00315       {
00316          // DirectDraw() implementation: last and first vertices should not be equal
00317          if (pp.front() == pp.back()) pp.pop_front();
00318          surf += AddPolygon(pp, fPolsBP);
00319       }
00320       bpols += (segN+2);
00321    }
00322    return surf;
00323 }
00324 
00325 //______________________________________________________________________________
00326 Float_t TEvePolygonSetProjected::MakePolygonsFromBS(Int_t* idxMap)
00327 {
00328    // Build polygons from the set of buffer segments.
00329    // First creates a segment pool according to reduced and projected points
00330    // and then build polygons from the pool.
00331 
00332    LSeg_t   segs;
00333    LSegIt_t it;
00334    Float_t  surf = 0; // surface of projected polygons
00335    TEveProjection *projection = fManager->GetProjection();
00336    for (UInt_t s = 0; s < fBuff->NbSegs(); ++s)
00337    {
00338       Bool_t duplicate = kFALSE;
00339       Int_t vo1,  vo2;  // idx from fBuff segment
00340       Int_t vor1, vor2; // mapped idx
00341       vo1 =  fBuff->fSegs[3*s + 1];
00342       vo2 =  fBuff->fSegs[3*s + 2]; //... skip color info
00343       vor1 = idxMap[vo1];
00344       vor2 = idxMap[vo2];
00345       if (vor1 == vor2) continue;
00346       // check duplicate
00347       for (it = segs.begin(); it != segs.end(); ++it)
00348       {
00349          Int_t vv1 = (*it).fV1;
00350          Int_t vv2 = (*it).fV2;
00351          if((vv1 == vor1 && vv2 == vor2) || (vv1 == vor2 && vv2 == vor1))
00352          {
00353             duplicate = kTRUE;
00354             continue;
00355          }
00356       }
00357       if (duplicate == kFALSE && projection->AcceptSegment(fPnts[vor1], fPnts[vor2], TEveProjection::fgEps))
00358          segs.push_back(Seg_t(vor1, vor2));
00359    }
00360 
00361    while ( ! segs.empty())
00362    {
00363       std::list<Int_t> pp; // points in current polygon
00364       pp.push_back(segs.front().fV1);
00365       Int_t tail = segs.front().fV2;
00366       segs.pop_front();
00367       Bool_t match = kTRUE;
00368       while (match && ! segs.empty())
00369       {
00370          for (LSegIt_t k = segs.begin(); k != segs.end(); ++k)
00371          {
00372             Int_t cv1 = (*k).fV1;
00373             Int_t cv2 = (*k).fV2;
00374             if (cv1 == tail || cv2 == tail)
00375             {
00376                pp.push_back(tail);
00377                tail = (cv1 == tail) ? cv2 : cv1;
00378                segs.erase(k);
00379                match = kTRUE;
00380                break;
00381             }
00382             else
00383             {
00384                match = kFALSE;
00385             }
00386          } // end for loop in the segment pool
00387          if (tail == pp.front())
00388             break;
00389       }
00390       surf += AddPolygon(pp, fPolsBS);
00391    }
00392    return surf;
00393 }
00394 
00395 //______________________________________________________________________________
00396 void  TEvePolygonSetProjected::ProjectBuffer3D()
00397 {
00398    // Project current buffer.
00399 
00400    // create map from original to projected and reduced point needed oly for geometry
00401    Int_t* idxMap = ProjectAndReducePoints();
00402 
00403    TEveProjection::EGeoMode_e mode = fManager->GetProjection()->GetGeoMode();
00404    switch (mode)
00405    {
00406       case TEveProjection::kGM_Polygons :
00407       {
00408          MakePolygonsFromBP(idxMap);
00409          fPolsBP.swap(fPols);
00410          break;
00411       }
00412       case TEveProjection::kGM_Segments :
00413       {
00414          MakePolygonsFromBS(idxMap);
00415          fPolsBS.swap(fPols);
00416          break;
00417       }
00418       case TEveProjection::kGM_Unknown:
00419       {
00420          // take projectopn with largest surface
00421         Float_t surfBP = MakePolygonsFromBP(idxMap);
00422         Float_t surfBS = MakePolygonsFromBS(idxMap);
00423          if (surfBS < surfBP)
00424          {
00425             fPolsBP.swap(fPols);
00426             fPolsBS.clear();
00427          }
00428          else
00429          {
00430             fPolsBS.swap(fPols);
00431             fPolsBP.clear();
00432          }
00433       }
00434       default:
00435          break;
00436    }
00437 
00438    delete [] idxMap;
00439    ResetBBox();
00440 }
00441 
00442 //______________________________________________________________________________
00443 Float_t TEvePolygonSetProjected::PolygonSurfaceXY(const TEvePolygonSetProjected::Polygon_t& p) const
00444 {
00445    // Calculate XY surface of a polygon.
00446 
00447    Float_t surf = 0;
00448    Int_t nPnts = p.fNPnts;
00449    for (Int_t i = 0; i < nPnts - 1; ++i)
00450    {
00451       Int_t a = p.fPnts[i];
00452       Int_t b = p.fPnts[i+1];
00453       surf += fPnts[a].fX * fPnts[b].fY - fPnts[a].fY * fPnts[b].fX;
00454    }
00455    return 0.5f * TMath::Abs(surf);
00456 }
00457 
00458 //______________________________________________________________________________
00459 void TEvePolygonSetProjected::DumpPolys() const
00460 {
00461    // Dump information about built polygons.
00462 
00463    printf("TEvePolygonSetProjected %d polygons\n", (Int_t)fPols.size());
00464    Int_t cnt = 0;
00465    for (vpPolygon_ci i = fPols.begin(); i!= fPols.end(); i++)
00466    {
00467       Int_t nPnts = (*i).fNPnts;
00468       printf("Points of polygon %d [Np = %d]:\n", ++cnt, nPnts);
00469       for (Int_t vi = 0; vi<nPnts; ++vi) {
00470          Int_t pi = (*i).fPnts[vi];
00471          printf("  (%f, %f, %f)", fPnts[pi].fX, fPnts[pi].fY, fPnts[pi].fZ);
00472       }
00473       printf(", surf=%f\n", PolygonSurfaceXY(*i));
00474    }
00475 }
00476 
00477 //______________________________________________________________________________
00478 void TEvePolygonSetProjected::DumpBuffer3D()
00479 {
00480    // Dump information about currenty projected buffer.
00481 
00482    Int_t* bpols = fBuff->fPols;
00483 
00484    for (UInt_t pi = 0; pi< fBuff->NbPols(); ++pi)
00485    {
00486       UInt_t segN = bpols[1];
00487       printf("%d polygon of %d has %d segments \n", pi, fBuff->NbPols(), segN);
00488 
00489       Int_t* seg =  &bpols[2];
00490       for (UInt_t a=0; a<segN; ++a)
00491       {
00492          Int_t a1 = fBuff->fSegs[3*seg[a] + 1];
00493          Int_t a2 = fBuff->fSegs[3*seg[a] + 2];
00494          printf("(%d, %d) \n", a1, a2);
00495          printf("ORIG points :(%f, %f, %f)  (%f, %f, %f)\n",
00496                 fBuff->fPnts[3*a1],fBuff->fPnts[3*a1+1], fBuff->fPnts[3*a1+2],
00497                 fBuff->fPnts[3*a2],fBuff->fPnts[3*a2+1], fBuff->fPnts[3*a2+2]);
00498       }
00499       printf("\n");
00500       bpols += (segN+2);
00501    }
00502 }

Generated on Tue Jul 5 14:16:13 2011 for ROOT_528-00b_version by  doxygen 1.5.1