Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
REveGeoPolyShape.cxx
Go to the documentation of this file.
1// @(#)root/eve7:$Id$
2// Author: Matevz Tadel 2007, 2018
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
12#include "Rtypes.h"
13#include <cassert>
14
15
17#include <ROOT/REveGeoShape.hxx>
18#include <ROOT/REveUtil.hxx>
19#include <ROOT/REveGluTess.hxx>
21
22#include "TBuffer3D.h"
23#include "TBuffer3DTypes.h"
24#define ROOT_CsgOps_cxx
25#include "CsgOps.h"
26
27#include "TGeoBoolNode.h"
28#include "TGeoCompositeShape.h"
29#include "TGeoMatrix.h"
30
31using namespace ROOT::Experimental;
32
33/** \class REveGeoPolyShape
34\ingroup REve
35Description of REveGeoPolyShape
36*/
37
38Bool_t REveGeoPolyShape::fgAutoEnforceTriangles = kTRUE;
39Bool_t REveGeoPolyShape::fgAutoCalculateNormals = kFALSE;
40
41void REveGeoPolyShape::SetAutoEnforceTriangles(Bool_t f) { fgAutoEnforceTriangles = f; }
45
46////////////////////////////////////////////////////////////////////////
47/// Function produces mesh for provided shape, applying matrix to the result
48
49std::unique_ptr<RootCsg::TBaseMesh> MakeGeoMesh(TGeoMatrix *matr, TGeoShape *shape)
50{
51 TGeoCompositeShape *comp = dynamic_cast<TGeoCompositeShape *> (shape);
52
53 std::unique_ptr<RootCsg::TBaseMesh> res;
54
55 if (!comp) {
56 std::unique_ptr<TBuffer3D> b3d(shape->MakeBuffer3D());
57
58 if (matr) {
59 Double_t *v = b3d->fPnts;
60 Double_t buf[3];
61 for (UInt_t i = 0; i < b3d->NbPnts(); ++i) {
62 buf[0] = v[i*3];
63 buf[1] = v[i*3+1];
64 buf[2] = v[i*3+2];
65 matr->LocalToMaster(buf, &v[i*3]);
66 }
67 }
68
69 res.reset(RootCsg::ConvertToMesh(*b3d.get()));
70 } else {
71 auto node = comp->GetBoolNode();
72
73 TGeoHMatrix mleft, mright;
74 if (matr) { mleft = *matr; mright = *matr; }
75
76 mleft.Multiply(node->GetLeftMatrix());
77 auto left = MakeGeoMesh(&mleft, node->GetLeftShape());
78
79 mright.Multiply(node->GetRightMatrix());
80 auto right = MakeGeoMesh(&mright, node->GetRightShape());
81
82 if (node->IsA() == TGeoUnion::Class()) res.reset(RootCsg::BuildUnion(left.get(), right.get()));
83 if (node->IsA() == TGeoIntersection::Class()) res.reset(RootCsg::BuildIntersection(left.get(), right.get()));
84 if (node->IsA() == TGeoSubtraction::Class()) res.reset(RootCsg::BuildDifference(left.get(), right.get()));
85 }
86
87 return res;
88}
89
90////////////////////////////////////////////////////////////////////////////////
91/// Produce all polygons from composite shape
92
94{
95 fOrigin[0] = cshape->GetOrigin()[0];
96 fOrigin[1] = cshape->GetOrigin()[1];
97 fOrigin[2] = cshape->GetOrigin()[2];
98 fDX = cshape->GetDX();
99 fDY = cshape->GetDY();
100 fDZ = cshape->GetDZ();
101
103
104 auto mesh = MakeGeoMesh(nullptr, cshape);
105
106 Int_t nv = mesh->NumberOfVertices();
107 fVertices.reserve(3 * nv);
108
109 for (Int_t i = 0; i < nv; ++i) {
110 auto v = mesh->GetVertex(i);
111 fVertices.insert(fVertices.end(), v, v + 3);
112 }
113
114 fNbPols = mesh->NumberOfPolys();
115
116 Int_t descSize = 0;
117
118 for (Int_t i = 0; i < fNbPols; ++i) descSize += mesh->SizeOfPoly(i) + 1;
119
120 fPolyDesc.reserve(descSize);
121
122 for (Int_t polyIndex = 0; polyIndex < fNbPols; ++polyIndex) {
123 Int_t polySize = mesh->SizeOfPoly(polyIndex);
124
125 fPolyDesc.push_back(polySize);
126
127 for (Int_t i = 0; i < polySize; ++i)
128 fPolyDesc.push_back(mesh->GetVertexIndex(polyIndex, i));
129 }
130
133}
134
135////////////////////////////////////////////////////////////////////////////////
136/// Produce all polygons from normal shape
137
139{
140 TGeoBBox *box = dynamic_cast<TGeoBBox *> (shape);
141
142 if (box) {
143 fOrigin[0] = box->GetOrigin()[0];
144 fOrigin[1] = box->GetOrigin()[1];
145 fOrigin[2] = box->GetOrigin()[2];
146 fDX = box->GetDX();
147 fDY = box->GetDY();
148 fDZ = box->GetDZ();
149 }
150
152
153 if (!shape->MakeBuffer3D())
154 {
155 std::cout << "Shape " << shape->GetName() << " has empty TBuffer3D\n";
156 return;
157 }
158
159 std::unique_ptr<TBuffer3D> b3d(shape->MakeBuffer3D());
160
161 SetFromBuff3D(*b3d.get());
162}
163
164////////////////////////////////////////////////////////////////////////////////
165
167{
168 // We know all elements are triangles. Or at least they should be.
169
170 rd.Reserve(fVertices.size(), fNormals.size(), 2 + fNbPols * 3);
171
172 for (auto &v: fVertices)
173 rd.PushV(v);
174
175 for (auto &n: fNormals)
176 rd.PushN(n);
177
179 rd.PushI(fNbPols);
180
181 // count number of index entries etc
182 for (Int_t i = 0, j = 0; i < fNbPols; ++i) {
183 assert(fPolyDesc[j] == 3);
184
185 rd.PushI(fPolyDesc[j + 1], fPolyDesc[j + 2], fPolyDesc[j + 3]);
186 j += 1 + fPolyDesc[j];
187 }
188}
189
190////////////////////////////////////////////////////////////////////////////////
191/// Set data-members from a Csg mesh.
192
193
195{
196 fNbPols = (Int_t) buffer.NbPols();
197
198 if (fNbPols == 0) return;
199
200 fVertices.insert(fVertices.end(), buffer.fPnts, buffer.fPnts + 3 * buffer.NbPnts());
201
202 Int_t *segs = buffer.fSegs;
203 Int_t *pols = buffer.fPols;
204
205 Int_t descSize = 0;
206
207 for (Int_t i = 0, j = 1; i < fNbPols; ++i, ++j)
208 {
209 descSize += pols[j] + 1;
210 j += pols[j] + 1;
211 }
212
213 fPolyDesc.resize(descSize);
214
215 for (Int_t numPol = 0, currInd = 0, j = 1; numPol < fNbPols; ++numPol)
216 {
217 Int_t segmentInd = pols[j] + j;
220 segmentInd--;
222 segmentInd--;
223 Int_t segEnds[] = {segs[s1 * 3 + 1], segs[s1 * 3 + 2],
224 segs[s2 * 3 + 1], segs[s2 * 3 + 2]};
225 Int_t numPnts[3];
226
227 if (segEnds[0] == segEnds[2]) {
228 numPnts[0] = segEnds[1]; numPnts[1] = segEnds[0]; numPnts[2] = segEnds[3];
229 } else if (segEnds[0] == segEnds[3]) {
230 numPnts[0] = segEnds[1]; numPnts[1] = segEnds[0]; numPnts[2] = segEnds[2];
231 } else if (segEnds[1] == segEnds[2]) {
232 numPnts[0] = segEnds[0]; numPnts[1] = segEnds[1]; numPnts[2] = segEnds[3];
233 } else {
234 numPnts[0] = segEnds[0]; numPnts[1] = segEnds[1]; numPnts[2] = segEnds[2];
235 }
236
237 fPolyDesc[currInd] = 3;
239 fPolyDesc[currInd++] = numPnts[0];
240 fPolyDesc[currInd++] = numPnts[1];
241 fPolyDesc[currInd++] = numPnts[2];
243
244 Int_t end = j + 1;
245 for (; segmentInd != end; segmentInd--) {
246 segEnds[0] = segs[pols[segmentInd] * 3 + 1];
247 segEnds[1] = segs[pols[segmentInd] * 3 + 2];
248 if (segEnds[0] == lastAdded) {
249 fPolyDesc[currInd++] = segEnds[1];
250 lastAdded = segEnds[1];
251 } else {
252 fPolyDesc[currInd++] = segEnds[0];
253 lastAdded = segEnds[0];
254 }
256 }
257 j += segmentCol + 2;
258 }
259
262}
263
264////////////////////////////////////////////////////////////////////////////////
265/// Use GLU tesselator to replace all polygons with N > 3 with triangles.
266/// After this call polygon descriptions are changed.
267/// New vertices are not expected -- exception is thrown if this is
268/// requested by the triangulator. Support for adding of new vertices can be
269/// provided.
270
272{
274
275 tc.ProcessData(fVertices, fPolyDesc, fNbPols);
276
277 fPolyDesc.swap(tc.RefPolyDesc());
278 fNbPols = tc.GetNTrianlges();
279}
280
281////////////////////////////////////////////////////////////////////////////////
282/// CalculateNormals per polygon (flat shading)
283
285{
286 fNormals.resize(3 * fNbPols);
287 if (fNbPols == 0) return;
288 Double_t *pnts = &fVertices[0];
289 for (Int_t i = 0, j = 0; i < fNbPols; ++i)
290 {
291 Int_t polEnd = fPolyDesc[j] + j + 1;
292 UInt_t norm[] = {fPolyDesc[j + 1], fPolyDesc[j + 2], fPolyDesc[j + 3]};
293 j += 4;
295 Int_t ngood = check;
296 if (check == 3) {
297 TMath::Normal2Plane(pnts + norm[0] * 3, pnts + norm[1] * 3,
298 pnts + norm[2] * 3, &fNormals[i * 3]);
299 j = polEnd;
300 continue;
301 }
302 while (j < polEnd)
303 {
304 norm[ngood++] = fPolyDesc[j++];
305 if (ngood == 3) {
307 if (ngood == 3) {
308 TMath::Normal2Plane(pnts + norm[0] * 3, pnts + norm[1] * 3,
309 pnts + norm[2] * 3, &fNormals[i * 3]);
310 j = polEnd;
311 break;
312 }
313 }
314 }
315 }
316}
317
318////////////////////////////////////////////////////////////////////////////////
319/// CheckPoints
320
322{
323 const Double_t * p1 = &fVertices[source[0] * 3];
324 const Double_t * p2 = &fVertices[source[1] * 3];
325 const Double_t * p3 = &fVertices[source[2] * 3];
326 Int_t retVal = 1;
327
328 if (Eq(p1, p2)) {
329 dest[0] = source[0];
330 if (!Eq(p1, p3) ) {
331 dest[1] = source[2];
332 retVal = 2;
333 }
334 } else if (Eq(p1, p3)) {
335 dest[0] = source[0];
336 dest[1] = source[1];
337 retVal = 2;
338 } else {
339 dest[0] = source[0];
340 dest[1] = source[1];
341 retVal = 2;
342 if (!Eq(p2, p3)) {
343 dest[2] = source[2];
344 retVal = 3;
345 }
346 }
347
348 return retVal;
349}
350
351////////////////////////////////////////////////////////////////////////////////
352/// Test equality of points with epsilon 1e-10.
353
355{
356 Double_t dx = TMath::Abs(p1[0] - p2[0]);
357 Double_t dy = TMath::Abs(p1[1] - p2[1]);
358 Double_t dz = TMath::Abs(p1[2] - p2[2]);
359 return (dx < 1e-10) && (dy < 1e-10) && (dz < 1e-10);
360}
361
362////////////////////////////////////////////////////////////////////////////////
363/// Fill the passed buffer 3D.
364
366{
368 {
369 // If writing core section all others will be invalid
370 b.ClearSectionsValid();
371
372 b.fID = const_cast<REveGeoPolyShape*>(this);
373 b.fColor = kMagenta;
374 b.fTransparency = 0;
375 b.fLocalFrame = kFALSE;
376 b.fReflection = kTRUE;
377
378 b.SetSectionsValid(TBuffer3D::kCore);
379 }
380
382 {
383 Int_t nvrt = fVertices.size() / 3;
384 Int_t nseg = 0;
385
386 std::map<Edge_t, Int_t> edges;
387
388 const UInt_t *pd = &fPolyDesc[0];
389 for (Int_t i = 0; i < fNbPols; ++i) {
390 Int_t nv = pd[0];
391 ++pd;
392 for (Int_t j = 0; j < nv; ++j) {
393 Edge_t e(pd[j], (j != nv - 1) ? pd[j + 1] : pd[0]);
394 if (edges.find(e) == edges.end()) {
395 edges.insert(std::make_pair(e, 0));
396 ++nseg;
397 }
398 }
399 pd += nv;
400 }
401
402 b.SetRawSizes(nvrt, 3*nvrt, nseg, 3*nseg, fNbPols, fNbPols+fPolyDesc.size());
403
404 memcpy(b.fPnts, &fVertices[0], sizeof(Double_t)*fVertices.size());
405
406 Int_t si = 0, scnt = 0;
407 for (auto &edge : edges) {
408 b.fSegs[si++] = 0;
409 b.fSegs[si++] = edge.first.fI;
410 b.fSegs[si++] = edge.first.fJ;
411 edge.second = scnt++;
412 }
413
414 Int_t pi = 0;
415 pd = &fPolyDesc[0];
416 for (Int_t i = 0; i < fNbPols; ++i) {
417 Int_t nv = pd[0];
418 ++pd;
419 b.fPols[pi++] = 0;
420 b.fPols[pi++] = nv;
421 for (Int_t j = 0; j < nv; ++j) {
422 b.fPols[pi++] = edges[Edge_t(pd[j], (j != nv - 1) ? pd[j + 1] : pd[0])];
423 }
424 pd += nv;
425 }
426
427 b.SetSectionsValid(TBuffer3D::kRawSizes | TBuffer3D::kRaw);
428 }
429}
430
431////////////////////////////////////////////////////////////////////////////////
432/// Fill static buffer 3D.
433
442
443////////////////////////////////////////////////////////////////////////////////
444/// Create buffer 3D and fill it with point/segment/poly data.
445
std::unique_ptr< RootCsg::TBaseMesh > MakeGeoMesh(TGeoMatrix *matr, TGeoShape *shape)
Function produces mesh for provided shape, applying matrix to the result.
#define b(i)
Definition RSha256.hxx:100
#define f(i)
Definition RSha256.hxx:104
#define s1(x)
Definition RSha256.hxx:91
#define e(i)
Definition RSha256.hxx:103
int Int_t
Signed integer 4 bytes (int)
Definition RtypesCore.h:60
constexpr Bool_t kFALSE
Definition RtypesCore.h:109
constexpr Bool_t kTRUE
Definition RtypesCore.h:108
@ kMagenta
Definition Rtypes.h:66
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t dest
REveGeoManagerHolder Exception-safe global variable holders.
Definition REveUtil.hxx:90
const TBuffer3D & GetBuffer3D(Int_t reqSections, Bool_t localFrame) const override
Fill static buffer 3D.
static void SetAutoCalculateNormals(Bool_t f)
void EnforceTriangles()
Use GLU tesselator to replace all polygons with N > 3 with triangles.
void BuildFromShape(TGeoShape *shape, Int_t n_seg=60)
Produce all polygons from normal shape.
void BuildFromComposite(TGeoCompositeShape *cshp, Int_t n_seg=60)
Produce all polygons from composite shape.
void FillBuffer3D(TBuffer3D &buffer, Int_t reqSections, Bool_t localFrame) const override
Fill the passed buffer 3D.
void CalculateNormals()
CalculateNormals per polygon (flat shading)
TBuffer3D * MakeBuffer3D() const override
Create buffer 3D and fill it with point/segment/poly data.
Int_t CheckPoints(const UInt_t *source, UInt_t *dest) const
CheckPoints.
void SetFromBuff3D(const TBuffer3D &buffer)
Set data-members from a Csg mesh.
static Bool_t Eq(const Double_t *p1, const Double_t *p2)
Test equality of points with epsilon 1e-10.
static TGeoManager * GetGeoManager()
Return static geo-manager that is used internally to make shapes lead a happy life.
Generic 3D primitive description class.
Definition TBuffer3D.h:18
Int_t * fPols
Definition TBuffer3D.h:124
UInt_t NbPols() const
Definition TBuffer3D.h:91
UInt_t NbPnts() const
Definition TBuffer3D.h:89
Int_t * fSegs
Definition TBuffer3D.h:123
Double_t * fPnts
Definition TBuffer3D.h:122
Box class.
Definition TGeoBBox.h:18
Double_t fDX
Definition TGeoBBox.h:21
Double_t fOrigin[3]
Definition TGeoBBox.h:24
Double_t fDY
Definition TGeoBBox.h:22
Double_t fDZ
Definition TGeoBBox.h:23
Composite shapes are Boolean combinations of two or more shape components.
Matrix class used for computing global transformations Should NOT be used for node definition.
Definition TGeoMatrix.h:459
void Multiply(const TGeoMatrix *right)
multiply to the right with an other transformation if right is identity matrix, just return
static TClass * Class()
Geometrical transformation package.
Definition TGeoMatrix.h:39
virtual void LocalToMaster(const Double_t *local, Double_t *master) const
convert a point by multiplying its column vector (x, y, z, 1) to matrix inverse
Base abstract class for all shapes.
Definition TGeoShape.h:25
const char * GetName() const override
Get the shape name.
virtual TBuffer3D * MakeBuffer3D() const
Definition TGeoShape.h:156
static TClass * Class()
static TClass * Class()
void box(Int_t pat, Double_t x1, Double_t y1, Double_t x2, Double_t y2)
Definition fillpatterns.C:1
const Int_t n
Definition legend1.C:16
Namespace for ROOT features in testing.
Definition TROOT.h:100
T * Normal2Plane(const T v1[3], const T v2[3], const T v3[3], T normal[3])
Calculates a normal vector of a plane.
Definition TMath.h:1305
Short_t Abs(Short_t d)
Returns the absolute value of parameter Short_t d.
Definition TMathBase.h:122