Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
REvePolygonSetProjected.cxx
Go to the documentation of this file.
1// @(#)root/eve7:$Id$
2// Authors: Matevz Tadel & Alja Mrak-Tadel: 2006, 2007
3
4/*************************************************************************
5 * Copyright (C) 1995-2019, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
13#include <ROOT/REveGeoShape.hxx>
15#include <ROOT/REveGluTess.hxx>
17
18#include "TBuffer3D.h"
19#include "TBuffer3DTypes.h"
20
21#include <cassert>
22
23using namespace ROOT::Experimental;
24
25namespace
26{
27 struct Seg_t
28 {
29 // Helper class for building 2D polygons from TBuffer3D.
30 Int_t fV1;
31 Int_t fV2;
32
33 Seg_t(Int_t i1=-1, Int_t i2=-1) : fV1(i1), fV2(i2) {}
34 };
35
36 typedef std::list<Seg_t> LSeg_t;
37}
38
39/** \class REvePolygonSetProjected
40\ingroup REve
41A set of projected polygons.
42Used for storage of projected geometrical shapes.
43
44Internal struct Polygon_t holds only indices into the master vertex
45array in REvePolygonSetProjected.
46*/
47
48////////////////////////////////////////////////////////////////////////////////
49/// Constructor.
50
51REvePolygonSetProjected::REvePolygonSetProjected(const std::string &n, const std::string &t) :
52 REveShape(n, t),
53 fBuff(),
54 fPnts()
55{
56}
57
58////////////////////////////////////////////////////////////////////////////////
59/// Destructor.
60
62{
63 fPols.clear();
64}
65
66////////////////////////////////////////////////////////////////////////////////
67/// Fill core part of JSON representation.
68
70{
71 Int_t ret = REveElement::WriteCoreJson(j, rnr_offset);
72
73 j["fNPnts"] = fPnts.size();
74
75 return ret;
76}
77
78////////////////////////////////////////////////////////////////////////////////
79/// Crates representation for rendering.
80/// This is complicated as we need to:
81/// - generate outlines;
82/// - convert polygons to triangles.
83/// ??? Should we check if polygons are front facing? It was not done in old EVE,
84/// just GL_FRONT_AND_BACK was used on top of gluTess.
85
87{
88 fRenderData = std::make_unique<REveRenderData>("makePolygonSetProjected", 3 * fPnts.size());
89
90 Int_t n_pols = fPols.size();
91 Int_t n_poly_info = 0;
92 for (auto &p : fPols) n_poly_info += 1 + p.NPoints();
93
94 std::vector<Double_t> verts;
95 verts.reserve(3 * fPnts.size());
96 std::vector<UInt_t> polys;
97 polys.reserve(n_poly_info);
98
99 for (auto &p : fPols)
100 {
101 polys.emplace_back(p.NPoints());
102 polys.insert(polys.end(), p.fPnts.begin(), p.fPnts.end());
103 }
104
105 for (unsigned i = 0; i < fPnts.size(); ++i)
106 {
107 verts.push_back(fPnts[i].fX);
108 verts.push_back(fPnts[i].fY);
109 verts.push_back(fPnts[i].fZ);
110 fRenderData->PushV(fPnts[i]);
111 }
112
113 Int_t n_trings = 0;
114 {
116
117 tc.ProcessData(verts, polys, n_pols);
118
119 polys.swap(tc.RefPolyDesc());
120 n_trings = tc.GetNTrianlges();
121 }
122
123 // Calculate size of index buffer.
124 Int_t n_idxbuff = 2 + 3 * n_trings + n_pols + n_poly_info;
125 fRenderData->Reserve(0,0,n_idxbuff);
126
127 assert(n_trings * 4 == (int)polys.size());
128
129 // Export triangles.
131 fRenderData->PushI(n_trings);
132 for (int i = 0; i < n_trings; ++i)
133 {
134 fRenderData->PushI(&polys[i*4 + 1], 3);
135 }
136
137 assert (fRenderData->SizeI() == 2 + 3 * n_trings);
138
139 // Export outlines.
140 for (auto &p : fPols)
141 {
143 fRenderData->PushI(p.NPoints());
144 fRenderData->PushI(p.fPnts);
145 }
146
147 assert (fRenderData->SizeI() == n_idxbuff);
148}
149
150////////////////////////////////////////////////////////////////////////////////
151/// Override of virtual method from TAttBBox.
152
154{
155 if (fPnts.size() > 0) {
156 BBoxInit();
157 for (unsigned pi = 0; pi < fPnts.size(); ++pi)
158 BBoxCheckPoint(fPnts[pi].fX, fPnts[pi].fY, fPnts[pi].fZ);
159 } else {
160 BBoxZero();
161 }
162}
163
164////////////////////////////////////////////////////////////////////////////////
165/// This is virtual method from base-class REveProjected.
166
168 REveProjectable* model)
169{
171
172 REveGeoShape* gre = dynamic_cast<REveGeoShape*>(model);
173 fBuff = gre->MakeBuffer3D();
174 CopyVizParams(gre);
175}
176
177////////////////////////////////////////////////////////////////////////////////
178/// Set depth (z-coordinate) of the projected points.
179
181{
182 SetDepthCommon(d, this, fBBox);
183
184 for (unsigned i = 0; i < fPnts.size(); ++i)
185 fPnts[i].fZ = fDepth;
186}
187
188////////////////////////////////////////////////////////////////////////////////
189/// This is virtual method from base-class REveProjected.
190
192{
193 if (!fBuff) return;
194
195 // drop polygons and projected/reduced points
196 fPols.clear();
198}
199
200////////////////////////////////////////////////////////////////////////////////
201/// Compare the two segments and check if the first index of first segment is starting.
202
204{
205 Int_t v0 = fBuff->fSegs[3*s0 + 1];
206 Int_t v2 = fBuff->fSegs[3*s1 + 1];
207 Int_t v3 = fBuff->fSegs[3*s1 + 2];
208 return v0 != v2 && v0 != v3;
209}
210
211////////////////////////////////////////////////////////////////////////////////
212/// Project and reduce buffer points.
213
215{
216 REveProjection* projection = fManager->GetProjection();
217
218 Int_t buffN = fBuff->NbPnts();
219 std::vector<REveVector> pnts; pnts.resize(buffN);
220 for (Int_t i = 0; i < buffN; ++i)
221 {
222 pnts[i].Set(fBuff->fPnts[3*i],fBuff->fPnts[3*i+1], fBuff->fPnts[3*i+2]);
223 projection->ProjectPoint(pnts[i].fX, pnts[i].fY, pnts[i].fZ, 0,
225 }
226
227 int npoints = 0;
228 std::vector<UInt_t> idxMap;
229 idxMap.resize(buffN);
230
231 std::vector<int> ra;
232 ra.resize(buffN); // list of reduced vertices
233 for (UInt_t v = 0; v < (UInt_t)buffN; ++v)
234 {
235 bool found = false;
236 for (Int_t k = 0; k < npoints; ++k)
237 {
238 if (pnts[v].SquareDistance(pnts[ra[k]]) < REveProjection::fgEpsSqr)
239 {
240 idxMap[v] = k;
241 found = true;
242 break;
243 }
244 }
245 // have not found a point inside epsilon, add new point in scaled array
246 if (!found)
247 {
248 idxMap[v] = npoints;
249 ra[npoints] = v;
250 ++npoints;
251 }
252 }
253
254 // write the array of scaled points
255 fPnts.resize(npoints);
256 for (Int_t idx = 0; idx < npoints; ++idx)
257 {
258 Int_t i = ra[idx];
259 projection->ProjectPoint(pnts[i].fX, pnts[i].fY, pnts[i].fZ, fDepth,
261 fPnts[idx].Set(pnts[i]);
262 }
263 // printf("reduced %d points of %d\n", fNPnts, N);
264
265 return idxMap;
266}
267
268////////////////////////////////////////////////////////////////////////////////
269/// Check if polygon has dimensions above REveProjection::fgEps and add it
270/// to a list if it is not a duplicate.
271
273{
274 if (pp.size() <= 2) return 0;
275
276 Float_t bbox[4] = { 1e6, -1e6, 1e6, -1e6 };
277 for (auto &&idx: pp)
278 {
279 if (fPnts[idx].fX < bbox[0]) bbox[0] = fPnts[idx].fX;
280 if (fPnts[idx].fX > bbox[1]) bbox[1] = fPnts[idx].fX;
281
282 if (fPnts[idx].fY < bbox[2]) bbox[2] = fPnts[idx].fY;
283 if (fPnts[idx].fY > bbox[3]) bbox[3] = fPnts[idx].fY;
284 }
286 if ((bbox[1]-bbox[0]) < eps || (bbox[3]-bbox[2]) < eps) return 0;
287
288 // Duplication
289 for (auto &&refP : pols)
290 {
291 if ((Int_t) pp.size() != refP.NPoints())
292 continue;
293
294 int start_idx = refP.FindPoint(pp.front());
295 if (start_idx < 0)
296 continue;
297 if (++start_idx >= refP.NPoints()) start_idx = 0;
298
299 // Same orientation duplicate
300 {
301 auto u = ++pp.begin();
302 Int_t pidx = start_idx;
303 while (u != pp.end())
304 {
305 if ((*u) != refP.fPnts[pidx])
306 break;
307 ++u;
308 if (++pidx >= refP.NPoints()) pidx = 0;
309 }
310 if (u == pp.end()) return 0;
311 }
312 // Inverse orientation duplicate
313 {
314 auto u = --pp.end();
315 Int_t pidx = start_idx;
316 while (u != pp.begin())
317 {
318 if ((*u) != refP.fPnts[pidx])
319 break;
320 --u;
321 if (++pidx >= refP.NPoints()) pidx = 0;
322 }
323 if (u == pp.begin()) return 0;
324 }
325 }
326
327 std::vector<UInt_t> pv(pp.size(), 0);
328 int count = 0;
329 for (auto &&u : pp) {
330 pv[count++] = u;
331 }
332
333 pols.emplace_back(std::move(pv));
334
335 return (bbox[1]-bbox[0]) * (bbox[3]-bbox[2]);
336}
337
338////////////////////////////////////////////////////////////////////////////////
339/// Build polygons from list of buffer polygons.
340
342{
343 REveProjection* projection = fManager->GetProjection();
344 Int_t *bpols = fBuff->fPols;
345 Float_t surf = 0; // surface of projected polygons
346 for (UInt_t pi = 0; pi < fBuff->NbPols(); ++pi)
347 {
348 std::list<UInt_t> pp; // points in current polygon
349 UInt_t segN = bpols[1];
350 Int_t *seg = &bpols[2];
351 // start idx in the fist segment depends of second segment
352 UInt_t tail, head;
353 if (IsFirstIdxHead(seg[0], seg[1]))
354 {
355 head = idxMap[fBuff->fSegs[3*seg[0] + 1]];
356 tail = idxMap[fBuff->fSegs[3*seg[0] + 2]];
357 }
358 else
359 {
360 head = idxMap[fBuff->fSegs[3*seg[0] + 2]];
361 tail = idxMap[fBuff->fSegs[3*seg[0] + 1]];
362 }
363 pp.emplace_back(head);
364 // printf("start idx head %d, tail %d\n", head, tail);
365 LSeg_t segs;
366 for (UInt_t s = 1; s < segN; ++s)
367 segs.emplace_back(fBuff->fSegs[3*seg[s] + 1],fBuff->fSegs[3*seg[s] + 2]);
368
369 for (auto &it: segs)
370 {
371 UInt_t mv1 = idxMap[it.fV1];
372 UInt_t mv2 = idxMap[it.fV2];
373
374 if ( ! projection->AcceptSegment(fPnts[mv1], fPnts[mv2], REveProjection::fgEps))
375 {
376 pp.clear();
377 break;
378 }
379 if (tail != pp.back()) pp.push_back(tail);
380 tail = (mv1 == tail) ? mv2 : mv1;
381 }
382
383 if ( ! pp.empty())
384 {
385 // DirectDraw() implementation: last and first vertices should not be equal
386 if (pp.front() == pp.back()) pp.pop_front();
387 surf += AddPolygon(pp, fPolsBP);
388 }
389 bpols += (segN+2);
390 }
391 return surf;
392}
393
394////////////////////////////////////////////////////////////////////////////////
395/// Build polygons from the set of buffer segments.
396/// First creates a segment pool according to reduced and projected points
397/// and then build polygons from the pool.
398
400{
401 LSeg_t segs;
402 Float_t surf = 0; // surface of projected polygons
403 REveProjection *projection = fManager->GetProjection();
404 for (UInt_t s = 0; s < fBuff->NbSegs(); ++s)
405 {
406 Bool_t duplicate = kFALSE;
407 Int_t vo1, vo2; // idx from fBuff segment
408 Int_t vor1, vor2; // mapped idx
409 vo1 = fBuff->fSegs[3*s + 1];
410 vo2 = fBuff->fSegs[3*s + 2]; //... skip color info
411 vor1 = idxMap[vo1];
412 vor2 = idxMap[vo2];
413 if (vor1 == vor2) continue;
414 // check duplicate
415 for (auto &seg: segs)
416 {
417 Int_t vv1 = seg.fV1;
418 Int_t vv2 = seg.fV2;
419 if((vv1 == vor1 && vv2 == vor2) || (vv1 == vor2 && vv2 == vor1))
420 {
421 duplicate = kTRUE;
422 continue;
423 }
424 }
425 if (duplicate == kFALSE && projection->AcceptSegment(fPnts[vor1], fPnts[vor2], REveProjection::fgEps))
426 segs.emplace_back(vor1, vor2);
427 }
428
429 while (!segs.empty())
430 {
431 std::list<UInt_t> pp; // points in current polygon
432 pp.push_back(segs.front().fV1);
433 UInt_t tail = segs.front().fV2;
434 segs.pop_front();
435 Bool_t match = kTRUE;
436 while (match && ! segs.empty())
437 {
438 for (auto k = segs.begin(); k != segs.end(); ++k)
439 {
440 UInt_t cv1 = (*k).fV1;
441 UInt_t cv2 = (*k).fV2;
442 if (cv1 == tail || cv2 == tail)
443 {
444 pp.emplace_back(tail);
445 tail = (cv1 == tail) ? cv2 : cv1;
446 segs.erase(k);
447 match = kTRUE;
448 break;
449 }
450 else
451 {
452 match = kFALSE;
453 }
454 } // end for loop in the segment pool
455 if (tail == pp.front())
456 break;
457 }
458 surf += AddPolygon(pp, fPolsBS);
459 }
460 return surf;
461}
462
463////////////////////////////////////////////////////////////////////////////////
464/// Project current buffer.
465
467{
468 // create map from original to projected and reduced point needed only for geometry
469 auto idxMap = ProjectAndReducePoints();
470
472 switch (mode) {
474 MakePolygonsFromBP(idxMap);
475 fPolsBP.swap(fPols);
476 break;
477 }
479 MakePolygonsFromBS(idxMap);
480 fPolsBS.swap(fPols);
481 break;
482 }
484 // take projection with largest surface
485 Float_t surfBP = MakePolygonsFromBP(idxMap);
486 Float_t surfBS = MakePolygonsFromBS(idxMap);
487 if (surfBS < surfBP) {
488 fPolsBP.swap(fPols);
489 fPolsBS.clear();
490 } else {
491 fPolsBS.swap(fPols);
492 fPolsBP.clear();
493 }
494 break;
495 }
496 default: break;
497 }
498
499 ResetBBox();
500}
501
502////////////////////////////////////////////////////////////////////////////////
503/// Calculate XY surface of a polygon.
504
506{
507 Float_t surf = 0;
508 Int_t nPnts = p.NPoints();
509 for (Int_t i = 0; i < nPnts - 1; ++i)
510 {
511 Int_t a = p.fPnts[i];
512 Int_t b = p.fPnts[i+1];
513 surf += fPnts[a].fX * fPnts[b].fY - fPnts[a].fY * fPnts[b].fX;
514 }
515 return 0.5f * TMath::Abs(surf);
516}
517
518////////////////////////////////////////////////////////////////////////////////
519/// Dump information about built polygons.
520
522{
523 printf("REvePolygonSetProjected %d polygons\n", (Int_t)fPols.size());
524 Int_t cnt = 0;
525 for ( auto &pol : fPols)
526 {
527 Int_t nPnts = pol.NPoints();
528 printf("Points of polygon %d [Np = %d]:\n", ++cnt, nPnts);
529 for (Int_t vi = 0; vi<nPnts; ++vi) {
530 Int_t pi = pol.fPnts[vi];
531 printf(" (%f, %f, %f)", fPnts[pi].fX, fPnts[pi].fY, fPnts[pi].fZ);
532 }
533 printf(", surf=%f\n", PolygonSurfaceXY(pol));
534 }
535}
536
537////////////////////////////////////////////////////////////////////////////////
538/// Dump information about currently projected buffer.
539
541{
542 Int_t* bpols = fBuff->fPols;
543
544 for (UInt_t pi = 0; pi< fBuff->NbPols(); ++pi)
545 {
546 UInt_t segN = bpols[1];
547 printf("%d polygon of %d has %d segments \n", pi, fBuff->NbPols(), segN);
548
549 Int_t* seg = &bpols[2];
550 for (UInt_t a=0; a<segN; ++a)
551 {
552 Int_t a1 = fBuff->fSegs[3*seg[a] + 1];
553 Int_t a2 = fBuff->fSegs[3*seg[a] + 2];
554 printf("(%d, %d) \n", a1, a2);
555 printf("ORIG points :(%f, %f, %f) (%f, %f, %f)\n",
556 fBuff->fPnts[3*a1],fBuff->fPnts[3*a1+1], fBuff->fPnts[3*a1+2],
557 fBuff->fPnts[3*a2],fBuff->fPnts[3*a2+1], fBuff->fPnts[3*a2+2]);
558 }
559 printf("\n");
560 bpols += (segN+2);
561 }
562}
#define d(i)
Definition RSha256.hxx:102
#define b(i)
Definition RSha256.hxx:100
#define s0(x)
Definition RSha256.hxx:90
#define a(i)
Definition RSha256.hxx:99
#define s1(x)
Definition RSha256.hxx:91
int Int_t
Definition RtypesCore.h:45
unsigned int UInt_t
Definition RtypesCore.h:46
const Bool_t kFALSE
Definition RtypesCore.h:92
const Bool_t kTRUE
Definition RtypesCore.h:91
segment * segs
Definition X3DBuffer.c:23
polygon * polys
Definition X3DBuffer.c:24
void ProcessData(const std::vector< Double_t > &verts, const std::vector< UInt_t > &polys, const Int_t n_polys)
ProcessData.
virtual Int_t WriteCoreJson(nlohmann::json &cj, Int_t rnr_offset)
Write core json.
std::unique_ptr< REveRenderData > fRenderData
Externally assigned and controlled user data.
virtual std::unique_ptr< TBuffer3D > MakeBuffer3D()
Create a TBuffer3D suitable for presentation of the shape.
void SetProjection(REveProjectionManager *mng, REveProjectable *model) override
This is virtual method from base-class REveProjected.
virtual void DumpPolys() const
Dump information about built polygons.
Bool_t IsFirstIdxHead(Int_t s0, Int_t s1)
Compare the two segments and check if the first index of first segment is starting.
vpPolygon_t fPolsBS
! polygons build from TBuffer3D segments
void BuildRenderData() override
Crates representation for rendering.
void DumpBuffer3D()
Dump information about currently projected buffer.
void UpdateProjection() override
This is virtual method from base-class REveProjected.
vpPolygon_t fPolsBP
! polygons build from TBuffer3D polygons
std::vector< UInt_t > ProjectAndReducePoints()
Project and reduce buffer points.
std::vector< REveVector > fPnts
! reduced and projected points
Float_t PolygonSurfaceXY(const Polygon_t &poly) const
Calculate XY surface of a polygon.
void ComputeBBox() override
Override of virtual method from TAttBBox.
Float_t MakePolygonsFromBS(std::vector< UInt_t > &idxMap)
Build polygons from the set of buffer segments.
Int_t WriteCoreJson(nlohmann::json &j, Int_t rnr_offset) override
Fill core part of JSON representation.
void SetDepthLocal(Float_t d) override
Set depth (z-coordinate) of the projected points.
Float_t MakePolygonsFromBP(std::vector< UInt_t > &idxMap)
Build polygons from list of buffer polygons.
Float_t AddPolygon(std::list< UInt_t > &pp, std::list< Polygon_t > &p)
Check if polygon has dimensions above REveProjection::fgEps and add it to a list if it is not a dupli...
virtual void SetProjection(REveProjectionManager *mng, REveProjectable *model)
Sets projection manager and reference in the projectable object.
void SetDepthCommon(Float_t d, REveElement *el, Float_t *bbox)
Utility function to update the z-values of the bounding-box.
REveProjectionManager Manager class for steering of projections and managing projected objects.
REveProjection Base for specific classes that implement non-linear projections.
virtual void ProjectPoint(Float_t &x, Float_t &y, Float_t &z, Float_t d, EPProc_e p=kPP_Full)=0
virtual Bool_t AcceptSegment(REveVector &, REveVector &, Float_t) const
void CopyVizParams(const REveElement *el) override
Copy visualization parameters from element el.
Definition REveShape.cxx:84
void BBoxCheckPoint(Float_t x, Float_t y, Float_t z)
Definition TAttBBox.h:58
void ResetBBox()
Definition TAttBBox.h:46
void BBoxZero(Float_t epsilon=0, Float_t x=0, Float_t y=0, Float_t z=0)
Create cube of volume (2*epsilon)^3 at (x,y,z).
Definition TAttBBox.cxx:42
void BBoxInit(Float_t infinity=1e6)
Dynamic Float_t[6] X(min,max), Y(min,max), Z(min,max)
Definition TAttBBox.cxx:29
Float_t * fBBox
Definition TAttBBox.h:20
const Int_t n
Definition legend1.C:16
Short_t Abs(Short_t d)
Definition TMathBase.h:120