]> git.uio.no Git - u/mrichter/AliRoot.git/blob - EVE/Reve/NLTPolygonSet.cxx
Merged EVE-dev-after-merge to EVE-dev into HEAD. Requires ROOT-5.17.04.
[u/mrichter/AliRoot.git] / EVE / Reve / NLTPolygonSet.cxx
1 #include "NLTPolygonSet.h"
2 #include "Reve/PODs.h"
3 #include "Reve/GeoNode.h"
4 #include "Reve/NLTProjector.h"
5
6 #include <TBuffer3D.h>
7 #include <TBuffer3DTypes.h>
8 #include <TVirtualPad.h>
9 #include <TVirtualViewer3D.h>
10
11 #include <list>
12
13 using namespace Reve;
14
15 namespace {
16   struct Seg {
17     Int_t v1;
18     Int_t v2;
19
20     Seg(Int_t i1=-1, Int_t i2=-1):v1(i1), v2(i2){};
21   };
22   typedef std::list<Seg>::iterator It_t;    
23 }
24
25
26 ClassImp(NLTPolygonSet)
27
28 /**************************************************************************/
29 NLTPolygonSet::NLTPolygonSet(const Text_t* n, const Text_t* t) :
30   RenderElementList(n, t),
31
32   fBuff(0),
33   fIdxMap(0),
34
35   fEps(0.05),
36   fNPnts(0),
37   fPnts(0),
38
39   fFillColor(5),
40   fLineColor(3),
41   fLineWidth(1),
42   fTransparency (0)
43 {
44   SetMainColorPtr(&fFillColor);
45 }
46
47 /**************************************************************************/
48
49 NLTPolygonSet::~NLTPolygonSet()
50 {
51   ClearPolygonSet();
52 }
53
54 void NLTPolygonSet::ClearPolygonSet()
55 {
56   // delete polygon vertex indices
57   Int_t* p;
58   for (vpPolygon_i i = fPols.begin(); i!= fPols.end(); i++)
59   {
60     p =  (*i).fPnts; delete [] p;
61   }
62   fPols.clear();
63   
64   // delete reduced points  
65   delete [] fPnts; fPnts = 0; fNPnts = 0;
66 }
67
68 /**************************************************************************/
69 void NLTPolygonSet::SetProjection(NLTProjector* proj, NLTProjectable* model)
70 {
71   NLTProjected::SetProjection(proj, model);
72   GeoShapeRnrEl* gsre = dynamic_cast<GeoShapeRnrEl*>(model);
73
74   fBuff = gsre->MakeBuffer3D();
75   if(fBuff)
76   {
77     SetMainColor(gsre->GetColor());
78     SetLineColor((Color_t)TColor::GetColorBright(gsre->GetColor()));
79     SetMainTransparency(gsre->GetMainTransparency());
80   }
81 }
82
83 /**************************************************************************/
84 void NLTPolygonSet::UpdateProjection()
85 {
86   if(fBuff == 0) return;
87
88   // drop polygons, and projected/reduced points
89   ClearPolygonSet();
90   ProjectBuffer3D();
91 }
92
93 //______________________________________________________________________________
94 Bool_t NLTPolygonSet::IsFirstIdxHead(Int_t s0, Int_t s1)
95 {
96   Int_t v0 = fBuff->fSegs[3*s0 + 1];
97   Int_t v2 = fBuff->fSegs[3*s1 + 1];
98   Int_t v3 = fBuff->fSegs[3*s1 + 2];
99   if(v0 != v2 && v0 != v3 )
100     return kTRUE;
101   else 
102     return kFALSE;
103 }
104
105 //______________________________________________________________________________
106 void NLTPolygonSet::ProjectAndReducePoints()
107 {
108   NLTProjection* projection = fProjector->GetProjection();
109   
110   Int_t N = fBuff->NbPnts();
111   Vector*  pnts  = new Vector[N];
112   for(Int_t i = 0; i<N; i++) 
113     pnts[i].Set(fBuff->fPnts[3*i],fBuff->fPnts[3*i+1], fBuff->fPnts[3*i+2]);
114   projection->Project(pnts, N, kFALSE);
115
116   fIdxMap   = new Int_t[N];  
117   Int_t* ra = new Int_t[N];  // list of reduced vertices
118
119   for(UInt_t v = 0; v < (UInt_t)N; ++v)
120   {
121     fIdxMap[v] = -1;
122     for(Int_t k = 0; k < fNPnts; ++k) 
123     {
124       if(pnts[v].SquareDistance(pnts[ra[k]]) < fEps*fEps)
125       {
126         fIdxMap[v] = k; 
127         break;
128       }
129     } 
130     // have not found a point inside epsilon, add new point in scaled array
131     if(fIdxMap[v] == -1)
132     {
133       fIdxMap[v] = fNPnts;
134       ra[fNPnts] = v;
135       ++fNPnts;
136     }
137     // printf("(%f, %f) vertex map %d -> %d \n", pnts[v*2], pnts[v*2 + 1], v, fIdxMap[v]);
138   }
139   
140   // create an array of scaled points
141   fPnts = new Vector[fNPnts];
142   for(Int_t i = 0; i < fNPnts; ++i)
143     fPnts[i].Set(pnts[ra[i]].x,  pnts[ra[i]].y, fDepth);
144   
145   delete [] ra;  
146   // printf("reduced %d points of %d\n", fNPnts, N);
147 }
148
149 //______________________________________________________________________________
150 void NLTPolygonSet::AddPolygon(std::list<Int_t>& pp)
151 {
152   if(pp.size() <= 2) return;
153
154   // dimension of bbox
155   Float_t bbox[] = { 1e6, -1e6, 1e6, -1e6, 1e6, -1e6 };
156   for (std::list<Int_t>::iterator u = pp.begin(); u!= pp.end(); u++) 
157   {
158     Int_t idx = *u; 
159     if(fPnts[idx].x < bbox[0]) bbox[0] = fPnts[idx].x;   
160     if(fPnts[idx].x > bbox[1]) bbox[1] = fPnts[idx].x;
161
162     if(fPnts[idx].y < bbox[2]) bbox[2] = fPnts[idx].y;   
163     if(fPnts[idx].y > bbox[3]) bbox[3] = fPnts[idx].y;
164
165     if(fPnts[idx].z < bbox[4]) bbox[4] = fPnts[idx].z;   
166     if(fPnts[idx].z > bbox[5]) bbox[5] = fPnts[idx].z;
167     // printf("bbox (%f, %f) (%f, %f)\n", bbox[1], bbox[0], bbox[3], bbox[2]);
168   }
169   if((bbox[1]-bbox[0])<fEps || (bbox[3]-bbox[2])<fEps) return;
170
171   // duplication
172   for (std::list<NLTPolygon>::iterator poi = fPols.begin(); poi!= fPols.end(); poi++)
173   {
174     NLTPolygon P = *poi;
175     if (pp.size() != (UInt_t)P.fNPnts) 
176       continue;      
177     std::list<Int_t>::iterator u = pp.begin();
178     Int_t pidx = P.FindPoint(*u);
179     if (pidx < 0)
180       continue;
181     while (u != pp.end())
182     {
183       if ((*u) != P.fPnts[pidx])
184         break;
185       ++u;
186       if (++pidx >= P.fNPnts) pidx = 0;
187     }
188     if (u == pp.end()) return;
189   }
190
191   // printf("add %d NLTPolygon points %d \n", fPols.size(), pp.size());
192   Int_t* pv = new Int_t[pp.size()];
193   Int_t count=0;
194   for( std::list<Int_t>::iterator u = pp.begin(); u!= pp.end(); u++){
195     pv[count] = *u;
196     count++;
197   }
198   fPols.push_back(NLTPolygon(pp.size(), pv));
199 } // AddPolygon
200
201 //______________________________________________________________________________
202 void NLTPolygonSet::MakePolygonsFromBP()
203 {
204   // build polygons from sorted list of segments : buff->fPols
205
206   //  printf("START NLTPolygonSet::MakePolygonsFromBP\n");
207   NLTProjection* projection = fProjector->GetProjection();
208   Int_t* bpols = fBuff->fPols;
209   for(UInt_t pi = 0; pi< fBuff->NbPols(); pi++) 
210   {
211     std::list<Int_t>  pp; // points in current polygon 
212     UInt_t Nseg = bpols[1]; 
213     Int_t* seg =  &bpols[2];
214     // start idx in the fist segment depends of second segment 
215     Int_t  tail, head;
216     Bool_t h = IsFirstIdxHead(seg[0], seg[1]);
217     if(h) {
218       head = fIdxMap[fBuff->fSegs[3*seg[0] + 1]];
219       tail = fIdxMap[fBuff->fSegs[3*seg[0] + 2]];
220     }
221     else {
222       head = fIdxMap[fBuff->fSegs[3*seg[0] + 2]];
223       tail = fIdxMap[fBuff->fSegs[3*seg[0] + 1]];
224     }
225     pp.push_back(head);
226     // printf("start idx head %d, tail %d\n", head, tail);
227     std::list<Seg> segs;  
228     for(UInt_t s = 1; s < Nseg; ++s)
229       segs.push_back(Seg(fBuff->fSegs[3*seg[s] + 1],fBuff->fSegs[3*seg[s] + 2]));
230     Bool_t accepted = kFALSE; 
231     for(std::list<Seg>::iterator it = segs.begin(); it != segs.end(); it++ )
232     { 
233       Int_t mv1 = fIdxMap[(*it).v1];
234       Int_t mv2 = fIdxMap[(*it).v2];         
235       accepted = projection->AcceptSegment(fPnts[mv1], fPnts[mv2], fEps);
236       if(accepted == kFALSE)
237       {
238         pp.clear();
239         break;
240       }   
241       if(tail != pp.back()) pp.push_back(tail);
242       tail = (mv1 == tail) ? mv2 :mv1;
243     }
244     // DirectDraw implementation: last and first vertices should not be equal
245     if(pp.empty() == kFALSE) 
246     {
247       if(pp.front() == pp.back()) pp.pop_front();
248       AddPolygon(pp);
249     }
250     bpols += (Nseg+2);
251   }
252 }// MakePolygonsFromBP
253
254 //______________________________________________________________________________
255 void NLTPolygonSet::MakePolygonsFromBS()
256 {
257   // builds polygons from the set of buffer segments
258
259   // create your own list of segments according to reduced and projected points
260   std::list<Seg> segs;  
261   std::list<Seg>::iterator it;
262   NLTProjection* projection = fProjector->GetProjection();
263   for(UInt_t s = 0; s < fBuff->NbSegs(); ++s)
264   {
265     Bool_t duplicate = kFALSE;
266     Int_t vo1, vo2;   // idx from fBuff segment
267     Int_t vor1, vor2; // mapped idx 
268     vo1 =  fBuff->fSegs[3*s + 1];
269     vo2 =  fBuff->fSegs[3*s + 2]; //... skip color info
270     vor1 = fIdxMap[vo1];
271     vor2 = fIdxMap[vo2];
272     if(vor1 == vor2) continue;
273     // check duplicate
274     for(it = segs.begin(); it != segs.end(); it++ ){
275       Int_t vv1 = (*it).v1;
276       Int_t vv2 = (*it).v2;
277       if((vv1 == vor1 && vv2 == vor2 )||(vv1 == vor2 && vv2 == vor1 )){
278         duplicate = kTRUE;
279         continue;
280       }
281     }
282     if(duplicate == kFALSE && projection->AcceptSegment(fPnts[vor1], fPnts[vor2], fEps))
283     {
284       segs.push_back(Seg(vor1, vor2));
285     }
286   }
287
288   // build polygons from segment pool
289   while(segs.empty() == kFALSE)
290   {
291     // printf("Start building polygon %d from %d segments in POOL \n", pols.size(), segs.size());
292     std::list<Int_t> pp; // points in current polygon
293     pp.push_back(segs.front().v1);
294     Int_t tail = segs.front().v2;
295     segs.pop_front();
296     Bool_t match = kTRUE;
297     while(match && segs.empty() == kFALSE)
298     {
299       // printf("second loop search tail %d \n",tail);
300       for(It_t k=segs.begin(); k!=segs.end(); ++k){
301         Int_t cv1 = (*k).v1;
302         Int_t cv2 = (*k).v2;
303         if( cv1 == tail || cv2 == tail){
304           // printf("found point %d  in %d,%d  \n", tail, cv1, cv2);
305           pp.push_back(tail);
306           tail = (cv1 == tail)? cv2:cv1;
307           It_t to_erase = k--;
308           segs.erase(to_erase);
309           match = kTRUE;
310           break;
311         }
312         else 
313         {
314           match = kFALSE;
315         }
316       } // end for loop in the segment pool
317       if(tail == pp.front())
318         break;
319     };
320     AddPolygon(pp);
321   }
322 }//MakePolygonsFromBS
323
324
325 /**************************************************************************/
326 void  NLTPolygonSet::ProjectBuffer3D()
327 {
328   //DumpBuffer3D();
329   ProjectAndReducePoints();
330
331   MakePolygonsFromBP();
332   if(fPols.empty())
333     MakePolygonsFromBS();
334   
335   delete []  fIdxMap;
336
337   ResetBBox();
338 }
339
340 /**************************************************************************/
341 void NLTPolygonSet::ComputeBBox()
342 {
343   // if(fPols.size() == 0) {
344   //  BBoxZero();
345   // }
346   
347   BBoxInit();
348   for(Int_t pi = 0; pi<fNPnts; pi++) 
349     BBoxCheckPoint(fPnts[pi].x, fPnts[pi].y, fPnts[pi].z );
350   AssertBBoxExtents(0.1);
351 }
352
353 /**************************************************************************/
354 void NLTPolygonSet::Paint(Option_t* )
355 {
356   if(fNPnts == 0) return;
357   TBuffer3D buffer(TBuffer3DTypes::kGeneric);
358
359   // Section kCore
360   buffer.fID           = this;
361   buffer.fColor        = GetMainColor();
362   buffer.fTransparency = fTransparency;
363   buffer.fLocalFrame   = false; 
364
365   buffer.SetSectionsValid(TBuffer3D::kCore);
366    
367   // We fill kCore on first pass and try with viewer
368   Int_t reqSections = gPad->GetViewer3D()->AddObject(buffer);
369   if (reqSections == TBuffer3D::kNone) {
370     return;
371   }
372 }
373
374 /**************************************************************************/
375 void NLTPolygonSet::DumpPolys() const
376 {
377   printf("NLTPolygonSet %d polygons\n", fPols.size());
378   for (vpPolygon_ci i = fPols.begin(); i!= fPols.end(); i++)
379   {
380     Int_t N =  (*i).fNPnts;
381     printf("polygon %d points :\n", N);    
382     for(Int_t vi = 0; vi<N; vi++) {
383       Int_t pi = (*i).fPnts[vi];
384       printf("(%f, %f, %f)", fPnts[pi].x, fPnts[pi].y, fPnts[pi].z);
385     }
386     printf("\n");
387   }
388 }
389
390 //______________________________________________________________________________
391 void NLTPolygonSet::DumpBuffer3D()
392 {
393   Int_t* bpols = fBuff->fPols;
394   
395   for(UInt_t pi = 0; pi< fBuff->NbPols(); pi++) 
396   {
397     UInt_t Nseg = bpols[1]; 
398     printf("%d polygon of %d has %d segments \n", pi,fBuff->NbPols(),Nseg);
399     
400     Int_t* seg =  &bpols[2];
401     for(UInt_t a=0; a<Nseg; a++)
402     {
403       Int_t a1 = fBuff->fSegs[3*seg[a]+ 1];
404       Int_t a2 = fBuff->fSegs[3*seg[a]+ 2];
405       printf("(%d, %d) \n", a1, a2);
406       printf("ORIG points :(%f, %f, %f)  (%f, %f, %f)\n", 
407              fBuff->fPnts[3*a1],fBuff->fPnts[3*a1+1], fBuff->fPnts[3*a1+2],
408              fBuff->fPnts[3*a2],fBuff->fPnts[3*a2+1], fBuff->fPnts[3*a2+2]);
409     }
410     printf("\n");
411     bpols += (Nseg+2);
412   }
413 }