24 using namespace ROOT::Experimental;
25 namespace REX = ROOT::Experimental;
35 Seg_t(Int_t i1=-1, Int_t i2=-1) : fV1(i1), fV2(i2) {}
38 typedef std::list<Seg_t> LSeg_t;
53 REvePolygonSetProjected::REvePolygonSetProjected(
const std::string &n,
const std::string &t) :
63 REvePolygonSetProjected::~REvePolygonSetProjected()
71 Int_t REvePolygonSetProjected::WriteCoreJson(nlohmann::json& j, Int_t rnr_offset)
73 Int_t ret = REveElement::WriteCoreJson(j, rnr_offset);
75 j[
"fNPnts"] = fPnts.size();
88 void REvePolygonSetProjected::BuildRenderData()
90 fRenderData = std::make_unique<REveRenderData>(
"makePolygonSetProjected", 3 * fPnts.size());
92 Int_t n_pols = fPols.size();
93 Int_t n_poly_info = 0;
94 for (
auto &p : fPols) n_poly_info += 1 + p.NPoints();
96 std::vector<Double_t> verts;
97 verts.reserve(3 * fPnts.size());
98 std::vector<Int_t> polys;
99 polys.reserve(n_poly_info);
101 for (
auto &p : fPols)
103 polys.emplace_back(p.NPoints());
104 polys.insert(polys.end(), p.fPnts.begin(), p.fPnts.end());
107 for (
unsigned i = 0; i < fPnts.size(); ++i)
109 verts.push_back(fPnts[i].fX);
110 verts.push_back(fPnts[i].fY);
111 verts.push_back(fPnts[i].fZ);
112 fRenderData->PushV(fPnts[i]);
117 EveGlu::TriangleCollector tc;
119 tc.ProcessData(verts, polys, n_pols);
121 polys.swap(tc.RefPolyDesc());
122 n_trings = tc.GetNTrianlges();
126 Int_t n_idxbuff = 2 + 3 * n_trings + n_pols + n_poly_info;
127 fRenderData->Reserve(0,0,n_idxbuff);
129 assert(n_trings * 4 == (
int)polys.size());
132 fRenderData->PushI(REveRenderData::GL_TRIANGLES);
133 fRenderData->PushI(n_trings);
134 for (
int i = 0; i < n_trings; ++i)
136 fRenderData->PushI(&polys[i*4 + 1], 3);
139 assert (fRenderData->SizeI() == 2 + 3 * n_trings);
142 for (
auto &p : fPols)
144 fRenderData->PushI(REveRenderData::GL_LINE_LOOP);
145 fRenderData->PushI(p.NPoints());
146 fRenderData->PushI(p.fPnts);
149 assert (fRenderData->SizeI() == n_idxbuff);
155 void REvePolygonSetProjected::ComputeBBox()
157 if (fPnts.size() > 0) {
159 for (
unsigned pi = 0; pi < fPnts.size(); ++pi)
160 BBoxCheckPoint(fPnts[pi].fX, fPnts[pi].fY, fPnts[pi].fZ);
169 void REvePolygonSetProjected::SetProjection(REveProjectionManager* mng,
170 REveProjectable* model)
172 REveProjected::SetProjection(mng, model);
174 REveGeoShape* gre =
dynamic_cast<REveGeoShape*
>(model);
175 fBuff = gre->MakeBuffer3D();
182 void REvePolygonSetProjected::SetDepthLocal(Float_t d)
184 SetDepthCommon(d,
this, fBBox);
186 for (
unsigned i = 0; i < fPnts.size(); ++i)
187 fPnts[i].fZ = fDepth;
193 void REvePolygonSetProjected::UpdateProjection()
205 Bool_t REvePolygonSetProjected::IsFirstIdxHead(Int_t s0, Int_t s1)
207 Int_t v0 = fBuff->fSegs[3*s0 + 1];
208 Int_t v2 = fBuff->fSegs[3*s1 + 1];
209 Int_t v3 = fBuff->fSegs[3*s1 + 2];
210 return v0 != v2 && v0 != v3;
216 std::vector<Int_t> REvePolygonSetProjected::ProjectAndReducePoints()
218 REveProjection* projection = fManager->GetProjection();
220 Int_t buffN = fBuff->NbPnts();
221 std::vector<REveVector> pnts; pnts.resize(buffN);
222 for (Int_t i = 0; i < buffN; ++i)
224 pnts[i].Set(fBuff->fPnts[3*i],fBuff->fPnts[3*i+1], fBuff->fPnts[3*i+2]);
225 projection->ProjectPoint(pnts[i].fX, pnts[i].fY, pnts[i].fZ, 0,
226 REveProjection::kPP_Plane);
230 std::vector<Int_t> idxMap;
231 idxMap.resize(buffN);
235 for (UInt_t v = 0; v < (UInt_t)buffN; ++v)
238 for (Int_t k = 0; k < npoints; ++k)
240 if (pnts[v].SquareDistance(pnts[ra[k]]) < REveProjection::fgEpsSqr)
256 fPnts.resize(npoints);
257 for (Int_t idx = 0; idx < npoints; ++idx)
260 projection->ProjectPoint(pnts[i].fX, pnts[i].fY, pnts[i].fZ, fDepth,
261 REveProjection::kPP_Distort);
262 fPnts[idx].Set(pnts[i]);
273 Float_t REvePolygonSetProjected::AddPolygon(std::list<Int_t> &pp, vpPolygon_t &pols)
275 if (pp.size() <= 2)
return 0;
277 Float_t bbox[4] = { 1e6, -1e6, 1e6, -1e6 };
280 if (fPnts[idx].fX < bbox[0]) bbox[0] = fPnts[idx].fX;
281 if (fPnts[idx].fX > bbox[1]) bbox[1] = fPnts[idx].fX;
283 if (fPnts[idx].fY < bbox[2]) bbox[2] = fPnts[idx].fY;
284 if (fPnts[idx].fY > bbox[3]) bbox[3] = fPnts[idx].fY;
286 Float_t eps = 2*REveProjection::fgEps;
287 if ((bbox[1]-bbox[0]) < eps || (bbox[3]-bbox[2]) < eps)
return 0;
290 for (
auto &&refP : pols)
292 if ((Int_t) pp.size() != refP.NPoints())
295 Int_t start_idx = refP.FindPoint(pp.front());
298 if (++start_idx >= refP.NPoints()) start_idx = 0;
302 auto u = ++pp.begin();
303 Int_t pidx = start_idx;
304 while (u != pp.end())
306 if ((*u) != refP.fPnts[pidx])
309 if (++pidx >= refP.NPoints()) pidx = 0;
311 if (u == pp.end())
return 0;
316 Int_t pidx = start_idx;
317 while (u != pp.begin())
319 if ((*u) != refP.fPnts[pidx])
322 if (++pidx >= refP.NPoints()) pidx = 0;
324 if (u == pp.begin())
return 0;
328 std::vector<int> pv(pp.size(), 0);
330 for (
auto &&u : pp) {
334 pols.emplace_back(std::move(pv));
336 return (bbox[1]-bbox[0]) * (bbox[3]-bbox[2]);
342 Float_t REvePolygonSetProjected::MakePolygonsFromBP(std::vector<Int_t> &idxMap)
344 REveProjection* projection = fManager->GetProjection();
345 Int_t *bpols = fBuff->fPols;
347 for (UInt_t pi = 0; pi < fBuff->NbPols(); ++pi)
350 UInt_t segN = bpols[1];
351 Int_t *seg = &bpols[2];
354 if (IsFirstIdxHead(seg[0], seg[1]))
356 head = idxMap[fBuff->fSegs[3*seg[0] + 1]];
357 tail = idxMap[fBuff->fSegs[3*seg[0] + 2]];
361 head = idxMap[fBuff->fSegs[3*seg[0] + 2]];
362 tail = idxMap[fBuff->fSegs[3*seg[0] + 1]];
364 pp.emplace_back(head);
367 for (UInt_t s = 1; s < segN; ++s)
368 segs.emplace_back(fBuff->fSegs[3*seg[s] + 1],fBuff->fSegs[3*seg[s] + 2]);
372 Int_t mv1 = idxMap[it.fV1];
373 Int_t mv2 = idxMap[it.fV2];
375 if ( ! projection->AcceptSegment(fPnts[mv1], fPnts[mv2], REveProjection::fgEps))
380 if (tail != pp.back()) pp.push_back(tail);
381 tail = (mv1 == tail) ? mv2 : mv1;
387 if (pp.front() == pp.back()) pp.pop_front();
388 surf += AddPolygon(pp, fPolsBP);
400 Float_t REvePolygonSetProjected::MakePolygonsFromBS(std::vector<Int_t> &idxMap)
404 REveProjection *projection = fManager->GetProjection();
405 for (UInt_t s = 0; s < fBuff->NbSegs(); ++s)
407 Bool_t duplicate = kFALSE;
410 vo1 = fBuff->fSegs[3*s + 1];
411 vo2 = fBuff->fSegs[3*s + 2];
414 if (vor1 == vor2)
continue;
416 for (
auto &seg: segs)
420 if((vv1 == vor1 && vv2 == vor2) || (vv1 == vor2 && vv2 == vor1))
426 if (duplicate == kFALSE && projection->AcceptSegment(fPnts[vor1], fPnts[vor2], REveProjection::fgEps))
427 segs.emplace_back(vor1, vor2);
430 while (!segs.empty())
433 pp.push_back(segs.front().fV1);
434 Int_t tail = segs.front().fV2;
436 Bool_t match = kTRUE;
437 while (match && ! segs.empty())
439 for (
auto k = segs.begin(); k != segs.end(); ++k)
441 Int_t cv1 = (*k).fV1;
442 Int_t cv2 = (*k).fV2;
443 if (cv1 == tail || cv2 == tail)
445 pp.emplace_back(tail);
446 tail = (cv1 == tail) ? cv2 : cv1;
456 if (tail == pp.front())
459 surf += AddPolygon(pp, fPolsBS);
467 void REvePolygonSetProjected::ProjectBuffer3D()
470 auto idxMap = ProjectAndReducePoints();
472 REveProjection::EGeoMode_e mode = fManager->GetProjection()->GetGeoMode();
474 case REveProjection::kGM_Polygons: {
475 MakePolygonsFromBP(idxMap);
479 case REveProjection::kGM_Segments: {
480 MakePolygonsFromBS(idxMap);
484 case REveProjection::kGM_Unknown: {
486 Float_t surfBP = MakePolygonsFromBP(idxMap);
487 Float_t surfBS = MakePolygonsFromBS(idxMap);
488 if (surfBS < surfBP) {
506 Float_t REvePolygonSetProjected::PolygonSurfaceXY(
const REvePolygonSetProjected::Polygon_t &p)
const
509 Int_t nPnts = p.NPoints();
510 for (Int_t i = 0; i < nPnts - 1; ++i)
512 Int_t a = p.fPnts[i];
513 Int_t b = p.fPnts[i+1];
514 surf += fPnts[a].fX * fPnts[b].fY - fPnts[a].fY * fPnts[b].fX;
516 return 0.5f * TMath::Abs(surf);
522 void REvePolygonSetProjected::DumpPolys()
const
524 printf(
"REvePolygonSetProjected %d polygons\n", (Int_t)fPols.size());
526 for (
auto &pol : fPols)
528 Int_t nPnts = pol.NPoints();
529 printf(
"Points of polygon %d [Np = %d]:\n", ++cnt, nPnts);
530 for (Int_t vi = 0; vi<nPnts; ++vi) {
531 Int_t pi = pol.fPnts[vi];
532 printf(
" (%f, %f, %f)", fPnts[pi].fX, fPnts[pi].fY, fPnts[pi].fZ);
534 printf(
", surf=%f\n", PolygonSurfaceXY(pol));
541 void REvePolygonSetProjected::DumpBuffer3D()
543 Int_t* bpols = fBuff->fPols;
545 for (UInt_t pi = 0; pi< fBuff->NbPols(); ++pi)
547 UInt_t segN = bpols[1];
548 printf(
"%d polygon of %d has %d segments \n", pi, fBuff->NbPols(), segN);
550 Int_t* seg = &bpols[2];
551 for (UInt_t a=0; a<segN; ++a)
553 Int_t a1 = fBuff->fSegs[3*seg[a] + 1];
554 Int_t a2 = fBuff->fSegs[3*seg[a] + 2];
555 printf(
"(%d, %d) \n", a1, a2);
556 printf(
"ORIG points :(%f, %f, %f) (%f, %f, %f)\n",
557 fBuff->fPnts[3*a1],fBuff->fPnts[3*a1+1], fBuff->fPnts[3*a1+2],
558 fBuff->fPnts[3*a2],fBuff->fPnts[3*a2+1], fBuff->fPnts[3*a2+2]);