// @(#)root/eve:$Id$
// Author: Matevz Tadel 2007

/*************************************************************************
 * Copyright (C) 1995-2007, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#include "TEveGeoPolyShape.h"
#include "TEveGeoShape.h"
#include "TEvePad.h"
#include "TEveUtil.h"

#include "TVirtualPad.h"
#include "TBuffer3D.h"
#include "TBuffer3DTypes.h"
#include "TGLScenePad.h"
#include "TGLFaceSet.h"

#include "TList.h"
#include "TGeoBoolNode.h"
#include "TGeoCompositeShape.h"
#include "TGeoMatrix.h"

//______________________________________________________________________________
// Description of TEveGeoPolyShape
//

ClassImp(TEveGeoPolyShape);

//______________________________________________________________________________
TEveGeoPolyShape::TEveGeoPolyShape() :
   TGeoBBox(),
   fNbPols(0)
{
   // Constructor.
}

//______________________________________________________________________________
TEveGeoPolyShape* TEveGeoPolyShape::Construct(TGeoCompositeShape *cshape, Int_t n_seg)
{
   // Static constructor from a composite shape.

   TEvePad       pad;
   TEvePadHolder gpad(kFALSE, &pad);
   TGLScenePad   scene_pad(&pad);
   pad.GetListOfPrimitives()->Add(cshape);
   pad.SetViewer3D(&scene_pad);

   TEveGeoManagerHolder gmgr(TEveGeoShape::GetGeoMangeur(), n_seg);

   scene_pad.BeginScene();
   {
      Double_t halfLengths[3] = { cshape->GetDX(), cshape->GetDY(), cshape->GetDZ() };

      TBuffer3D buff(TBuffer3DTypes::kComposite);
      buff.fID           = cshape;
      buff.fLocalFrame   = kTRUE;
      buff.SetLocalMasterIdentity();
      buff.SetAABoundingBox(cshape->GetOrigin(), halfLengths);
      buff.SetSectionsValid(TBuffer3D::kCore|TBuffer3D::kBoundingBox);

      Bool_t paintComponents = kTRUE;

      // Start a composite shape, identified by this buffer
      if (TBuffer3D::GetCSLevel() == 0)
         paintComponents = gPad->GetViewer3D()->OpenComposite(buff);

      TBuffer3D::IncCSLevel();

      // Paint the boolean node - will add more buffers to viewer
      TGeoMatrix *gst = TGeoShape::GetTransform();
      TGeoShape::SetTransform(TEveGeoShape::GetGeoHMatrixIdentity());
      if (paintComponents) cshape->GetBoolNode()->Paint("");
      TGeoShape::SetTransform(gst);
      // Close the composite shape
      if (TBuffer3D::DecCSLevel() == 0)
         gPad->GetViewer3D()->CloseComposite();
   }
   scene_pad.EndScene();
   pad.SetViewer3D(0);

   TGLFaceSet* fs = dynamic_cast<TGLFaceSet*>(scene_pad.FindLogical(cshape));
   if (!fs) {
      ::Warning("TEveGeoPolyShape::Construct", "Failed extracting CSG tesselation for shape '%s'.", cshape->GetName());
      return 0;
   }

   TEveGeoPolyShape *egps = new TEveGeoPolyShape;
   egps->SetFromFaceSet(fs);
   egps->fOrigin[0] = cshape->GetOrigin()[0];
   egps->fOrigin[1] = cshape->GetOrigin()[1];
   egps->fOrigin[2] = cshape->GetOrigin()[2];
   egps->fDX = cshape->GetDX();
   egps->fDY = cshape->GetDY();
   egps->fDZ = cshape->GetDZ();

   return egps;
}

//______________________________________________________________________________
void TEveGeoPolyShape::SetFromFaceSet(TGLFaceSet* fs)
{
   // Set data-members from a face-set.

   fVertices = fs->GetVertices();
   fPolyDesc = fs->GetPolyDesc();
   fNbPols   = fs->GetNbPols();
}

//______________________________________________________________________________
void TEveGeoPolyShape::FillBuffer3D(TBuffer3D& b, Int_t reqSections, Bool_t) const
{
   // Fill the passed buffer 3D.

   if (reqSections & TBuffer3D::kCore)
   {
      // If writing core section all others will be invalid
      b.ClearSectionsValid();

      b.fID = const_cast<TEveGeoPolyShape*>(this);
      b.fColor = 0;
      b.fTransparency = 0;
      b.fLocalFrame = kFALSE;
      b.fReflection = kTRUE;

      b.SetSectionsValid(TBuffer3D::kCore);
   }

   if (reqSections & TBuffer3D::kRawSizes || reqSections & TBuffer3D::kRaw)
   {
      UInt_t nvrt = fVertices.size() / 3;
      UInt_t nseg = 0;

      std::map<Edge_t, Int_t> edges;

      const Int_t *pd = &fPolyDesc[0];
      for (UInt_t i = 0; i < fNbPols; ++i)
      {
         UInt_t nv = pd[0]; ++pd;
         for (UInt_t j = 0; j < nv; ++j)
         {
            Edge_t e(pd[j], (j != nv - 1) ? pd[j+1] : pd[0]);
            if (edges.find(e) == edges.end())
            {
               edges.insert(std::make_pair(e, 0));
               ++nseg;
            }
         }
         pd += nv;
      }

      b.SetRawSizes(nvrt, 3*nvrt, nseg, 3*nseg, fNbPols, fNbPols+fPolyDesc.size());

      memcpy(b.fPnts, &fVertices[0], sizeof(Double_t)*fVertices.size());

      Int_t si = 0, scnt = 0;
      for (std::map<Edge_t, Int_t>::iterator i = edges.begin(); i != edges.end(); ++i)
      {
         b.fSegs[si++] = 0;
         b.fSegs[si++] = i->first.fI;
         b.fSegs[si++] = i->first.fJ;
         i->second = scnt++;
      }

      Int_t pi = 0;
      pd = &fPolyDesc[0];
      for (UInt_t i = 0; i < fNbPols; ++i)
      {
         UInt_t nv = pd[0]; ++pd;
         b.fPols[pi++] = 0;
         b.fPols[pi++] = nv;
         for (UInt_t j = 0; j < nv; ++j)
         {
            b.fPols[pi++] = edges[Edge_t(pd[j], (j != nv - 1) ? pd[j+1] : pd[0])];
         }
         pd += nv;
      }



      b.SetSectionsValid(TBuffer3D::kRawSizes | TBuffer3D::kRaw);
   }
}

//______________________________________________________________________________
const TBuffer3D& TEveGeoPolyShape::GetBuffer3D(Int_t reqSections, Bool_t localFrame) const
{
   // Fill static buffer 3D.

   static TBuffer3D buf(TBuffer3DTypes::kGeneric);

   FillBuffer3D(buf, reqSections, localFrame);

   return buf;
}

//______________________________________________________________________________
TBuffer3D* TEveGeoPolyShape::MakeBuffer3D() const
{
   // Create buffer 3D and fill it with point/segment/poly data.

   TBuffer3D* buf = new TBuffer3D(TBuffer3DTypes::kGeneric);

   FillBuffer3D(*buf, TBuffer3D::kCore | TBuffer3D::kRawSizes | TBuffer3D::kRaw, kFALSE);

   return buf;
}
 TEveGeoPolyShape.cxx:1
 TEveGeoPolyShape.cxx:2
 TEveGeoPolyShape.cxx:3
 TEveGeoPolyShape.cxx:4
 TEveGeoPolyShape.cxx:5
 TEveGeoPolyShape.cxx:6
 TEveGeoPolyShape.cxx:7
 TEveGeoPolyShape.cxx:8
 TEveGeoPolyShape.cxx:9
 TEveGeoPolyShape.cxx:10
 TEveGeoPolyShape.cxx:11
 TEveGeoPolyShape.cxx:12
 TEveGeoPolyShape.cxx:13
 TEveGeoPolyShape.cxx:14
 TEveGeoPolyShape.cxx:15
 TEveGeoPolyShape.cxx:16
 TEveGeoPolyShape.cxx:17
 TEveGeoPolyShape.cxx:18
 TEveGeoPolyShape.cxx:19
 TEveGeoPolyShape.cxx:20
 TEveGeoPolyShape.cxx:21
 TEveGeoPolyShape.cxx:22
 TEveGeoPolyShape.cxx:23
 TEveGeoPolyShape.cxx:24
 TEveGeoPolyShape.cxx:25
 TEveGeoPolyShape.cxx:26
 TEveGeoPolyShape.cxx:27
 TEveGeoPolyShape.cxx:28
 TEveGeoPolyShape.cxx:29
 TEveGeoPolyShape.cxx:30
 TEveGeoPolyShape.cxx:31
 TEveGeoPolyShape.cxx:32
 TEveGeoPolyShape.cxx:33
 TEveGeoPolyShape.cxx:34
 TEveGeoPolyShape.cxx:35
 TEveGeoPolyShape.cxx:36
 TEveGeoPolyShape.cxx:37
 TEveGeoPolyShape.cxx:38
 TEveGeoPolyShape.cxx:39
 TEveGeoPolyShape.cxx:40
 TEveGeoPolyShape.cxx:41
 TEveGeoPolyShape.cxx:42
 TEveGeoPolyShape.cxx:43
 TEveGeoPolyShape.cxx:44
 TEveGeoPolyShape.cxx:45
 TEveGeoPolyShape.cxx:46
 TEveGeoPolyShape.cxx:47
 TEveGeoPolyShape.cxx:48
 TEveGeoPolyShape.cxx:49
 TEveGeoPolyShape.cxx:50
 TEveGeoPolyShape.cxx:51
 TEveGeoPolyShape.cxx:52
 TEveGeoPolyShape.cxx:53
 TEveGeoPolyShape.cxx:54
 TEveGeoPolyShape.cxx:55
 TEveGeoPolyShape.cxx:56
 TEveGeoPolyShape.cxx:57
 TEveGeoPolyShape.cxx:58
 TEveGeoPolyShape.cxx:59
 TEveGeoPolyShape.cxx:60
 TEveGeoPolyShape.cxx:61
 TEveGeoPolyShape.cxx:62
 TEveGeoPolyShape.cxx:63
 TEveGeoPolyShape.cxx:64
 TEveGeoPolyShape.cxx:65
 TEveGeoPolyShape.cxx:66
 TEveGeoPolyShape.cxx:67
 TEveGeoPolyShape.cxx:68
 TEveGeoPolyShape.cxx:69
 TEveGeoPolyShape.cxx:70
 TEveGeoPolyShape.cxx:71
 TEveGeoPolyShape.cxx:72
 TEveGeoPolyShape.cxx:73
 TEveGeoPolyShape.cxx:74
 TEveGeoPolyShape.cxx:75
 TEveGeoPolyShape.cxx:76
 TEveGeoPolyShape.cxx:77
 TEveGeoPolyShape.cxx:78
 TEveGeoPolyShape.cxx:79
 TEveGeoPolyShape.cxx:80
 TEveGeoPolyShape.cxx:81
 TEveGeoPolyShape.cxx:82
 TEveGeoPolyShape.cxx:83
 TEveGeoPolyShape.cxx:84
 TEveGeoPolyShape.cxx:85
 TEveGeoPolyShape.cxx:86
 TEveGeoPolyShape.cxx:87
 TEveGeoPolyShape.cxx:88
 TEveGeoPolyShape.cxx:89
 TEveGeoPolyShape.cxx:90
 TEveGeoPolyShape.cxx:91
 TEveGeoPolyShape.cxx:92
 TEveGeoPolyShape.cxx:93
 TEveGeoPolyShape.cxx:94
 TEveGeoPolyShape.cxx:95
 TEveGeoPolyShape.cxx:96
 TEveGeoPolyShape.cxx:97
 TEveGeoPolyShape.cxx:98
 TEveGeoPolyShape.cxx:99
 TEveGeoPolyShape.cxx:100
 TEveGeoPolyShape.cxx:101
 TEveGeoPolyShape.cxx:102
 TEveGeoPolyShape.cxx:103
 TEveGeoPolyShape.cxx:104
 TEveGeoPolyShape.cxx:105
 TEveGeoPolyShape.cxx:106
 TEveGeoPolyShape.cxx:107
 TEveGeoPolyShape.cxx:108
 TEveGeoPolyShape.cxx:109
 TEveGeoPolyShape.cxx:110
 TEveGeoPolyShape.cxx:111
 TEveGeoPolyShape.cxx:112
 TEveGeoPolyShape.cxx:113
 TEveGeoPolyShape.cxx:114
 TEveGeoPolyShape.cxx:115
 TEveGeoPolyShape.cxx:116
 TEveGeoPolyShape.cxx:117
 TEveGeoPolyShape.cxx:118
 TEveGeoPolyShape.cxx:119
 TEveGeoPolyShape.cxx:120
 TEveGeoPolyShape.cxx:121
 TEveGeoPolyShape.cxx:122
 TEveGeoPolyShape.cxx:123
 TEveGeoPolyShape.cxx:124
 TEveGeoPolyShape.cxx:125
 TEveGeoPolyShape.cxx:126
 TEveGeoPolyShape.cxx:127
 TEveGeoPolyShape.cxx:128
 TEveGeoPolyShape.cxx:129
 TEveGeoPolyShape.cxx:130
 TEveGeoPolyShape.cxx:131
 TEveGeoPolyShape.cxx:132
 TEveGeoPolyShape.cxx:133
 TEveGeoPolyShape.cxx:134
 TEveGeoPolyShape.cxx:135
 TEveGeoPolyShape.cxx:136
 TEveGeoPolyShape.cxx:137
 TEveGeoPolyShape.cxx:138
 TEveGeoPolyShape.cxx:139
 TEveGeoPolyShape.cxx:140
 TEveGeoPolyShape.cxx:141
 TEveGeoPolyShape.cxx:142
 TEveGeoPolyShape.cxx:143
 TEveGeoPolyShape.cxx:144
 TEveGeoPolyShape.cxx:145
 TEveGeoPolyShape.cxx:146
 TEveGeoPolyShape.cxx:147
 TEveGeoPolyShape.cxx:148
 TEveGeoPolyShape.cxx:149
 TEveGeoPolyShape.cxx:150
 TEveGeoPolyShape.cxx:151
 TEveGeoPolyShape.cxx:152
 TEveGeoPolyShape.cxx:153
 TEveGeoPolyShape.cxx:154
 TEveGeoPolyShape.cxx:155
 TEveGeoPolyShape.cxx:156
 TEveGeoPolyShape.cxx:157
 TEveGeoPolyShape.cxx:158
 TEveGeoPolyShape.cxx:159
 TEveGeoPolyShape.cxx:160
 TEveGeoPolyShape.cxx:161
 TEveGeoPolyShape.cxx:162
 TEveGeoPolyShape.cxx:163
 TEveGeoPolyShape.cxx:164
 TEveGeoPolyShape.cxx:165
 TEveGeoPolyShape.cxx:166
 TEveGeoPolyShape.cxx:167
 TEveGeoPolyShape.cxx:168
 TEveGeoPolyShape.cxx:169
 TEveGeoPolyShape.cxx:170
 TEveGeoPolyShape.cxx:171
 TEveGeoPolyShape.cxx:172
 TEveGeoPolyShape.cxx:173
 TEveGeoPolyShape.cxx:174
 TEveGeoPolyShape.cxx:175
 TEveGeoPolyShape.cxx:176
 TEveGeoPolyShape.cxx:177
 TEveGeoPolyShape.cxx:178
 TEveGeoPolyShape.cxx:179
 TEveGeoPolyShape.cxx:180
 TEveGeoPolyShape.cxx:181
 TEveGeoPolyShape.cxx:182
 TEveGeoPolyShape.cxx:183
 TEveGeoPolyShape.cxx:184
 TEveGeoPolyShape.cxx:185
 TEveGeoPolyShape.cxx:186
 TEveGeoPolyShape.cxx:187
 TEveGeoPolyShape.cxx:188
 TEveGeoPolyShape.cxx:189
 TEveGeoPolyShape.cxx:190
 TEveGeoPolyShape.cxx:191
 TEveGeoPolyShape.cxx:192
 TEveGeoPolyShape.cxx:193
 TEveGeoPolyShape.cxx:194
 TEveGeoPolyShape.cxx:195
 TEveGeoPolyShape.cxx:196
 TEveGeoPolyShape.cxx:197
 TEveGeoPolyShape.cxx:198
 TEveGeoPolyShape.cxx:199
 TEveGeoPolyShape.cxx:200
 TEveGeoPolyShape.cxx:201
 TEveGeoPolyShape.cxx:202
 TEveGeoPolyShape.cxx:203
 TEveGeoPolyShape.cxx:204
 TEveGeoPolyShape.cxx:205
 TEveGeoPolyShape.cxx:206
 TEveGeoPolyShape.cxx:207
 TEveGeoPolyShape.cxx:208
 TEveGeoPolyShape.cxx:209
 TEveGeoPolyShape.cxx:210
 TEveGeoPolyShape.cxx:211