TGLMarchingCubes.h

Go to the documentation of this file.
00001 // @(#)root/gl:$Id: TGLMarchingCubes.h 33600 2010-05-21 09:24:32Z rdm $
00002 // Author:  Timur Pocheptsov  06/01/2009
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2009, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 #ifndef ROOT_TGLMarchingCubes
00013 #define ROOT_TGLMarchingCubes
00014 
00015 #include <vector>
00016 
00017 #ifndef ROOT_TH3
00018 #include "TH3.h"
00019 #endif
00020 
00021 #ifndef ROOT_TGLIsoMesh
00022 #include "TGLIsoMesh.h"
00023 #endif
00024 #ifndef ROOT_TKDEAdapter
00025 #include "TKDEAdapter.h"
00026 #endif
00027 
00028 /*
00029 Implementation of "marching cubes" algortihm for GL module. Used by
00030 TGLTF3Painter and TGLIsoPainter.
00031 Good and clear algorithm explanation can be found here:
00032 http://local.wasp.uwa.edu.au/~pbourke/geometry/polygonise/
00033 */
00034 
00035 class TF3;
00036 class TKDEFGT;
00037 
00038 namespace Rgl {
00039 namespace Mc {
00040 
00041 /*
00042 Some routines, values and tables for marching cube method.
00043 */
00044 extern const UInt_t  eInt[256];
00045 extern const Float_t vOff[8][3];
00046 extern const UChar_t eConn[12][2];
00047 extern const Float_t eDir[12][3];
00048 extern const Int_t   conTbl[256][16];
00049 
00050 /*
00051 "T" prefix in class names is only for code-style checker.
00052 */
00053 
00054 /*
00055 TCell is a cube from marching cubes algorithm.
00056 It has "type" - defines, which vertices
00057 are under iso level, which are above.
00058 
00059 Vertices numeration:
00060 
00061            |z
00062            |
00063            4____________7
00064           /|           /|
00065          / |          / |
00066         /  |         /  |
00067        /   |        /   |
00068       5____|_______6    |
00069       |    0_______|____3______ y
00070       |   /        |   /
00071       |  /         |  /
00072       | /          | /
00073       |/           |/
00074       1____________2
00075      /
00076     /x
00077 
00078 TCell's "type" is 8-bit number, one bit per vertex.
00079 So, if vertex 1 and 2 are under iso-surface, type
00080 will be:
00081 
00082  7 6 5 4 3 2 1 0 (bit number)
00083 [0 0 0 0 0 1 1 0] bit pattern
00084 
00085 type == 6.
00086 
00087 Edges numeration:
00088 
00089            |z
00090            |
00091            |_____7______
00092           /|           /|
00093          / |          / |
00094        4/  8         6  11
00095        /   |        /   |
00096       /____|5______/    |
00097       |    |_____3_|____|______ y
00098       |   /        |   /
00099       9  /        10  /
00100       | /0         | /2
00101       |/           |/
00102       /____________/
00103      /      1
00104     /x
00105 
00106 There are 12 edges, any of them can be intersected by iso-surface
00107 (not all 12 simultaneously). Edge's intersection is a vertex in
00108 iso-mesh's vertices array, cell holds index of this vertex in
00109 fIds array.
00110 fVals holds "scalar field" or density values in vertices [0, 7].
00111 
00112 "V" parameter is the type to hold such values.
00113 */
00114 
00115 template<class V>
00116 class TCell {
00117 public:
00118    TCell() : fType(), fIds(), fVals()
00119    {
00120       //TCell ctor.
00121       //Such mem-initializer list can produce
00122       //warnings with some versions of MSVC,
00123       //but this list is what I want.
00124    }
00125 
00126    UInt_t     fType;
00127    UInt_t     fIds[12];
00128    V          fVals[8];
00129 };
00130 
00131 /*
00132 TSlice of marching cubes' grid. Has W * H cells.
00133 If you have TH3 hist, GetNbinsX() is W and GetNbinsY() is H.
00134 */
00135 template<class V>
00136 class TSlice {
00137 public:
00138    TSlice()
00139    {
00140    }
00141 
00142    void ResizeSlice(UInt_t w, UInt_t h)
00143    {
00144       fCells.resize(w * h);
00145    }
00146 
00147    std::vector<TCell<V> > fCells;
00148 private:
00149    TSlice(const TSlice &rhs);
00150    TSlice & operator = (const TSlice &rhs);
00151 };
00152 
00153 /*
00154 Mesh builder requires generic "data source": it can
00155 be a wrapped TH3 object, a wrapped TF3 object or some
00156 "density estimator" object.
00157 Mesh builder inherits this data source type.
00158 
00159 TH3Adapter is one of such data sources.
00160 It has _direct_ access to TH3 internal data.
00161 GetBinContent(i, j, k) is a virtual function
00162 and it calls two other virtual functions - this
00163 is very expensive if you call GetBinContent
00164 several million times as I do in marching cubes.
00165 
00166 "H" parameter is one of TH3 classes,
00167 "E" is the type of internal data.
00168 
00169 For example, H == TH3C, E == Char_t.
00170 */
00171 
00172 template<class H, class E>
00173 class TH3Adapter {
00174 protected:
00175 
00176    typedef E    ElementType_t;
00177 
00178    TH3Adapter()
00179       : fSrc(0), fW(0), fH(0), fD(0), fSliceSize(0)
00180    {
00181    }
00182 
00183    UInt_t GetW()const
00184    {
00185       return fW - 2;
00186    }
00187 
00188    UInt_t GetH()const
00189    {
00190       return fH - 2;
00191    }
00192 
00193    UInt_t GetD()const
00194    {
00195       return fD - 2;
00196    }
00197 
00198    void SetDataSource(const H *hist)
00199    {
00200       fSrc = hist->GetArray();
00201       fW   = hist->GetNbinsX() + 2;
00202       fH   = hist->GetNbinsY() + 2;
00203       fD   = hist->GetNbinsZ() + 2;
00204       fSliceSize = fW * fH;
00205    }
00206 
00207    void FetchDensities()const{}//Do nothing.
00208 
00209    ElementType_t GetData(UInt_t i, UInt_t j, UInt_t k)const
00210    {
00211       i += 1;
00212       j += 1;
00213       k += 1;
00214       return fSrc[k * fSliceSize + j * fW + i];
00215    }
00216 
00217    const ElementType_t *fSrc;
00218    UInt_t fW;
00219    UInt_t fH;
00220    UInt_t fD;
00221    UInt_t fSliceSize;
00222 };
00223 
00224 /*
00225 TF3Adapter. Lets TMeshBuilder to use TF3 as a 3d array.
00226 TF3Adapter, TF3EdgeSplitter (see below) and TMeshBuilder<TF3, ValueType>
00227 need TGridGeometry<ValueType>, so TGridGeometry is a virtual base.
00228 */
00229 
00230 class TF3Adapter : protected virtual TGridGeometry<Double_t> {
00231 protected:
00232    typedef Double_t ElementType_t;
00233 
00234    TF3Adapter() : fTF3(0), fW(0), fH(0), fD(0)
00235    {
00236    }
00237 
00238    UInt_t GetW()const
00239    {
00240       return fW;
00241    }
00242 
00243    UInt_t GetH()const
00244    {
00245       return fH;
00246    }
00247 
00248    UInt_t GetD()const
00249    {
00250       return fD;
00251    }
00252 
00253    void SetDataSource(const TF3 *f);
00254 
00255    void FetchDensities()const{}//Do nothing.
00256 
00257    Double_t GetData(UInt_t i, UInt_t j, UInt_t k)const;
00258 
00259    const TF3 *fTF3;//TF3 data source.
00260    //TF3 grid's dimensions.
00261    UInt_t     fW;
00262    UInt_t     fH;
00263    UInt_t     fD;
00264 };
00265 
00266 /*
00267 TSourceAdapterSelector is aux. class used by TMeshBuilder to
00268 select "data-source" base depending on data-source type.
00269 */
00270 template<class> class TSourceAdapterSelector;
00271 
00272 template<>
00273 class TSourceAdapterSelector<TH3C> {
00274 public:
00275    typedef TH3Adapter<TH3C, Char_t> Type_t;
00276 };
00277 
00278 template<>
00279 class TSourceAdapterSelector<TH3S> {
00280 public:
00281    typedef TH3Adapter<TH3S, Short_t> Type_t;
00282 };
00283 
00284 template<>
00285 class TSourceAdapterSelector<TH3I> {
00286 public:
00287    typedef TH3Adapter<TH3I, Int_t> Type_t;
00288 };
00289 
00290 template<>
00291 class TSourceAdapterSelector<TH3F> {
00292 public:
00293    typedef TH3Adapter<TH3F, Float_t> Type_t;
00294 };
00295 
00296 template<>
00297 class TSourceAdapterSelector<TH3D> {
00298 public:
00299    typedef TH3Adapter<TH3D, Double_t> Type_t;
00300 };
00301 
00302 template<>
00303 class TSourceAdapterSelector<TF3> {
00304 public:
00305    typedef TF3Adapter Type_t;
00306 };
00307 
00308 template<>
00309 class TSourceAdapterSelector<TKDEFGT> {
00310 public:
00311    typedef Fgt::TKDEAdapter Type_t;
00312 };
00313 
00314 /*
00315 Edge splitter is the second base class for TMeshBuilder.
00316 Its task is to split cell's edge by adding new vertex
00317 into mesh.
00318 Default splitter is used by TH3 and KDE.
00319 */
00320 
00321 template<class E, class V>
00322 V GetOffset(E val1, E val2, V iso)
00323 {
00324    const V delta = val2 - val1;
00325    if (!delta)
00326       return 0.5f;
00327    return (iso - val1) / delta;
00328 }
00329 
00330 template<class H, class E, class V>
00331 class TDefaultSplitter : protected virtual TGridGeometry<V> {
00332 protected:
00333    void SetNormalEvaluator(const H * /*source*/)
00334    {
00335    }
00336    void SplitEdge(TCell<E> & cell, TIsoMesh<V> * mesh, UInt_t i,
00337                   V x, V y, V z, V iso)const
00338 {
00339    V v[3];
00340    const V offset = GetOffset(cell.fVals[eConn[i][0]],
00341                               cell.fVals[eConn[i][1]],
00342                               iso);
00343    v[0] = x + (vOff[eConn[i][0]][0] + offset * eDir[i][0]) * this->fStepX;
00344    v[1] = y + (vOff[eConn[i][0]][1] + offset * eDir[i][1]) * this->fStepY;
00345    v[2] = z + (vOff[eConn[i][0]][2] + offset * eDir[i][2]) * this->fStepZ;
00346    cell.fIds[i] = mesh->AddVertex(v);
00347 }
00348 
00349 
00350 };
00351 
00352 /*
00353 TF3's edge splitter. Calculates new vertex and surface normal
00354 in this vertex using TF3.
00355 */
00356 
00357 class TF3EdgeSplitter : protected virtual TGridGeometry<Double_t> {
00358 protected:
00359    TF3EdgeSplitter() : fTF3(0)
00360    {
00361    }
00362 
00363    void SetNormalEvaluator(const TF3 *tf3)
00364    {
00365       fTF3 = tf3;
00366    }
00367 
00368    void SplitEdge(TCell<Double_t> & cell, TIsoMesh<Double_t> * mesh, UInt_t i,
00369                   Double_t x, Double_t y, Double_t z, Double_t iso)const;
00370 
00371    const TF3 *fTF3;
00372 };
00373 
00374 /*
00375 TSplitterSelector is aux. class to select "edge-splitter" base
00376 for TMeshBuilder.
00377 */
00378 
00379 template<class, class> class TSplitterSelector;
00380 
00381 template<class V>
00382 class TSplitterSelector<TH3C, V> {
00383 public:
00384    typedef TDefaultSplitter<TH3C, Char_t, V> Type_t;
00385 };
00386 
00387 template<class V>
00388 class TSplitterSelector<TH3S, V> {
00389 public:
00390    typedef TDefaultSplitter<TH3S, Short_t, V> Type_t;
00391 };
00392 
00393 template<class V>
00394 class TSplitterSelector<TH3I, V> {
00395 public:
00396    typedef TDefaultSplitter<TH3I, Int_t, V> Type_t;
00397 };
00398 
00399 template<class V>
00400 class TSplitterSelector<TH3F, V> {
00401 public:
00402    typedef TDefaultSplitter<TH3F, Float_t, V> Type_t;
00403 };
00404 
00405 template<class V>
00406 class TSplitterSelector<TH3D, V> {
00407 public:
00408    typedef TDefaultSplitter<TH3D, Double_t, V> Type_t;
00409 };
00410 
00411 template<class V>
00412 class TSplitterSelector<TKDEFGT, V> {
00413 public:
00414    typedef TDefaultSplitter<TKDEFGT, Float_t, Float_t> Type_t;
00415 };
00416 
00417 template<class V>
00418 class TSplitterSelector<TF3, V> {
00419 public:
00420    typedef TF3EdgeSplitter Type_t;
00421 };
00422 
00423 /*
00424 Mesh builder. Polygonizes scalar field - TH3, TF3 or
00425 something else (some density estimator as data-source).
00426 
00427 ValueType is Float_t or Double_t - the type of vertex'
00428 x,y,z components.
00429 */
00430 
00431 template<class DataSource, class ValueType>
00432 class TMeshBuilder : public TSourceAdapterSelector<DataSource>::Type_t,
00433                      public TSplitterSelector<DataSource, ValueType>::Type_t
00434 {
00435 private:
00436    //Two base classes.
00437    typedef typename TSourceAdapterSelector<DataSource>::Type_t       DataSourceBase_t;
00438    typedef typename TSplitterSelector<DataSource, ValueType>::Type_t SplitterBase_t;
00439    //Using declarations required, since these are
00440    //type-dependant names in template.
00441    using DataSourceBase_t::GetW;
00442    using DataSourceBase_t::GetH;
00443    using DataSourceBase_t::GetD;
00444    using DataSourceBase_t::GetData;
00445    using SplitterBase_t::SplitEdge;
00446 
00447    typedef typename DataSourceBase_t::ElementType_t ElementType_t;
00448 
00449    typedef TCell<ElementType_t>  CellType_t;
00450    typedef TSlice<ElementType_t> SliceType_t;
00451    typedef TIsoMesh<ValueType>   MeshType_t;
00452 
00453 public:
00454    TMeshBuilder(Bool_t averagedNormals, ValueType eps = 1e-7)
00455       : fAvgNormals(averagedNormals), fMesh(0), fIso(), fEpsilon(eps)
00456    {
00457    }
00458 
00459    void BuildMesh(const DataSource *src, const TGridGeometry<ValueType> &geom,
00460                   MeshType_t *mesh, ValueType iso);
00461 
00462 private:
00463 
00464    Bool_t      fAvgNormals;
00465    SliceType_t fSlices[2];
00466    MeshType_t *fMesh;
00467    ValueType   fIso;
00468    ValueType   fEpsilon;
00469 
00470    void NextStep(UInt_t depth, const SliceType_t *prevSlice,
00471                  SliceType_t *curr)const;
00472 
00473    void BuildFirstCube(SliceType_t *slice)const;
00474    void BuildRow(SliceType_t *slice)const;
00475    void BuildCol(SliceType_t *slice)const;
00476    void BuildSlice(SliceType_t *slice)const;
00477    void BuildFirstCube(UInt_t depth, const SliceType_t *prevSlice,
00478                        SliceType_t *slice)const;
00479    void BuildRow(UInt_t depth, const SliceType_t *prevSlice,
00480                  SliceType_t *slice)const;
00481    void BuildCol(UInt_t depth, const SliceType_t *prevSlice,
00482                  SliceType_t *slice)const;
00483    void BuildSlice(UInt_t depth, const SliceType_t *prevSlice,
00484                    SliceType_t *slice)const;
00485 
00486    void BuildNormals()const;
00487 
00488    TMeshBuilder(const TMeshBuilder &rhs);
00489    TMeshBuilder & operator = (const TMeshBuilder &rhs);
00490 };
00491 
00492 }//namespace Mc
00493 }//namespace Rgl
00494 
00495 #endif

Generated on Tue Jul 5 14:16:47 2011 for ROOT_528-00b_version by  doxygen 1.5.1