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