arbeit
Main Page | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Namespace Members | Compound Members | File Members

VolField.cpp

Go to the documentation of this file.
00001 //------------------------------------------------------------------------
00002 //
00003 //   Joe Kniss
00004 //     6-20-03
00005 //                   ________    ____   ___ 
00006 //                  |        \  /    | /  /
00007 //                  +---+     \/     |/  /
00008 //                  +--+|  |\    /|     < 
00009 //                  |  ||  | \  / |  |\  \ 
00010 //                  |      |  \/  |  | \  \ 
00011 //                   \_____|      |__|  \__\
00012 //                       Copyright  2003 
00013 //                      Joe Michael Kniss
00014 //                   <<< jmk@cs.utah.edu >>>
00015 //               "All Your Base are Belong to Us"
00016 //-------------------------------------------------------------------------
00017 
00018 ///VolField.cpp
00019 
00020 #include "VolField.h"
00021 #include <mathGutz.h>
00022 #include <util/simPow.h>
00023 
00024 using namespace gutz;
00025 using namespace glift;
00026 using namespace std;
00027 
00028 ///////////////////////////////////////////////////////////////////////////
00029 ///////////////////////////////////////////////////////////////////////////
00030 /// VolField
00031 ///////////////////////////////////////////////////////////////////////////
00032 ///////////////////////////////////////////////////////////////////////////
00033 
00034 ///////////////////////////////////////////////////////////////////////////
00035 /// Construct
00036 ///////////////////////////////////////////////////////////////////////////
00037 VolField::VolField()
00038 : SimBase(),
00039 NrroSPVec(),        ///empty field
00040 _on(false),         /// nothing to have on  
00041 _up(false),         /// doesn't need update
00042 _bricked(false),    /// no bricks yet
00043 _texquality(BEST),  ///best quality texture
00044 _texUnit(-1)
00045 {}
00046 
00047 VolField::VolField(Nrro *n)
00048 : SimBase(),
00049 NrroSPVec(1,NrroSP(n)), ///the original data 
00050 _on(true),              ///on by default
00051 _up(true),              ///needs update
00052 _bricked(false),        ///not bricked
00053 _texquality(BEST),      ///best quality texture
00054 _texUnit(-1)
00055 {}    
00056 
00057 VolField::VolField(NrroSP n)
00058 : SimBase(),
00059 NrroSPVec(1,n), 
00060 _on(true), 
00061 _up(true),
00062 _bricked(false),
00063 _texquality(BEST),
00064 _texUnit(-1)
00065 {}
00066 
00067 void VolField::setNrro(NrroSP nrro, unsigned int n)
00068 {
00069    for(int i=int(size())-1; i<int(n); ++i)
00070    {
00071       NrroSPVec::push_back(NrroSP());
00072       derr("setNrro(), inserting NULL nrro objects");
00073    }
00074    NrroSPVec::operator[](n) = nrro; 
00075 }
00076 
00077 ///////////////////////////////////////////////////////////////////////////
00078 /// Update Field
00079 ///////////////////////////////////////////////////////////////////////////
00080 void  VolField::update()
00081 {
00082    /// nothing changed? nothing to do
00083    if(!getUpdate()) return;
00084 
00085    /// reset everything
00086    if(isBricked())
00087    {
00088       nukeBricks();
00089    }
00090    clearTex();
00091 
00092    /// update reset
00093    setUpdate(false);
00094 }
00095 
00096 ///////////////////////////////////////////////////////////////////////////
00097 /// Generate Texture
00098 ///////////////////////////////////////////////////////////////////////////
00099 SingleTexSP VolField::genTexture(unsigned int n)
00100 {       
00101    for(unsigned int i=g_max(int(_tex.size())-1,0); i<n; ++i)
00102    {
00103       _tex.push_back(SingleTexSP());
00104       derr("genTexture(),inserting null textures");
00105    }
00106 
00107    if(n == _tex.size())
00108       _tex.push_back(SingleTexSP());
00109 
00110    if(!_tex[n])
00111    {
00112       NrroSP nrro = NrroSPVec::operator[](n);
00113       if(!nrro.isNull())
00114       {
00115          _tex[n] = loadNrroTexture(nrro, _texquality);
00116       }
00117       else
00118       {
00119          derr("genTex(), nrro not valid, returning null texture");
00120       }
00121    }
00122    if(!_tex[n]) /// texture still not valid!!! badness
00123    {
00124       derr("genTex(), ERROR:: invalid texture returned!");
00125    }
00126    return _tex[n];
00127 }
00128 
00129 ///////////////////////////////////////////////////////////////////////////
00130 /// Generate Brick Texture
00131 ///////////////////////////////////////////////////////////////////////////
00132 glift::SingleTexSP VolField::genBrickTexture(unsigned int n)
00133 {
00134    if(isBricked())
00135       return genTexture(n+1);
00136    return genTexture(n);
00137 }
00138 
00139 ///////////////////////////////////////////////////////////////////////////
00140 /// Check Dims
00141 ///////////////////////////////////////////////////////////////////////////
00142 /// check to see if our dimensions match another's exactly
00143 bool  VolField::checkDims(SmartPtr<VolField> f)
00144 {
00145    /// check every brick
00146    for(unsigned int i=0; i<size(); ++i)
00147    {
00148       NrroSP n1 = getNrro(i);
00149       NrroSP n2 = f->getNrro(i);
00150       /// error checking abounds
00151       if(n2.isNull() || n1.isNull())
00152       {
00153          derr("checkDims(), NULL nrro comparision");
00154       }
00155       /// check to make sure they are the same dimension
00156       if(n1->dim() != n1->dim())
00157       {
00158          return false;
00159       }
00160       /// check each axis
00161       for(int d=0; d<n1->dim(0); ++d)
00162       {
00163          if(n1->dim(d) != n2->dim(d))
00164             return false;
00165       }
00166    }
00167    return true;
00168 }
00169 
00170 ///////////////////////////////////////////////////////////////////////////
00171 /// get Brick
00172 ///////////////////////////////////////////////////////////////////////////
00173 NrroSP  VolField::getBrick(unsigned int i)
00174 {
00175    if(isBricked() && i<size())
00176    {
00177       return getNrro(i+1);
00178    }
00179    /// I don't know if this is reasonable!
00180    /// but I just don't want to crash!
00181    return getNrro(0);
00182 }
00183 
00184 ///////////////////////////////////////////////////////////////////////////
00185 /// num Bricks
00186 ///////////////////////////////////////////////////////////////////////////
00187 unsigned int VolField::numBricks()
00188 {
00189    if(isBricked() && size() > 1)
00190    {
00191       return size()-1;
00192    }
00193    else
00194    {
00195       return 1;
00196    }
00197 }
00198 
00199 ///////////////////////////////////////////////////////////////////////////
00200 /// nuke bricks
00201 ///////////////////////////////////////////////////////////////////////////
00202 void VolField::nukeBricks()
00203 {
00204    /// not bricked, nothing to do
00205    if(!isBricked()) return;
00206 
00207    /// pop off all nrro bricks
00208    /// leave 0, that's the original data
00209    for(unsigned int i=0; i<size()-1; ++i)
00210    {
00211       NrroSPVec::pop_back();
00212    }
00213 
00214    /// reset bricked
00215    setBricked(false);
00216 }
00217 
00218 ///////////////////////////////////////////////////////////////////////////
00219 /// Generate a nice brick
00220 ///////////////////////////////////////////////////////////////////////////
00221 NrroSP VolField::genBrick(vec3i pos, vec3i size, NrroSP nin)
00222 {
00223    /// set up the arrays we need for nrro croping
00224    int min[4] = {-1, 
00225       pos.x, 
00226       pos.y, 
00227       pos.z};
00228    int max[4] = {-1, 
00229       g_min(nin->dim(1)-1,pos.x+size.x-1), 
00230       g_min(nin->dim(2)-1,pos.y+size.y-1), 
00231       g_min(nin->dim(3)-1,pos.z+size.z-1)};
00232 
00233    /// crop that sucker
00234    NrroSP nnew = nin->crop(min,max);
00235 
00236    if(!nnew.isNull())
00237    {
00238       /// check if we have a remainder to pad out ?
00239       if((pos.x+size.x > nin->dim(1)) || 
00240          (pos.y+size.y > nin->dim(2)) || 
00241          (pos.z+size.z > nin->dim(3)))
00242       {
00243          /// arrays we need for nrro padding
00244          int pmin[4] = {0,0,0,0};
00245          int pmax[4] = {nnew->dim(0)-1, size.x-1, size.y-1, size.z-1};
00246          nnew = nnew->pad(pmin,pmax,Nrro::BLEED); ///pad out to brick size
00247       }
00248    }
00249    return nnew;
00250 }
00251 
00252 ///////////////////////////////////////////////////////////////////////////
00253 /// Brick, just do it
00254 ///////////////////////////////////////////////////////////////////////////
00255 void VolField::brick(gutz::vec3i bdim)
00256 {
00257    if(getUpdate()) update();
00258    if(isBricked()) return;
00259 
00260    NrroSP n = getNrro(0);
00261 
00262    //cerr << " dim " << n->dim() << endl;
00263    //cerr << " dims " << n->dim(0) << " " << n->dim(1) << " " << n->dim(2) << " " << n->dim(3) << endl;
00264    vec3i vsize(n->dim(1), n->dim(2), n->dim(3));
00265 
00266    /// how many bricks will we need?
00267    /// if the original volume is smaller than
00268    /// the maxBrick dim, we will generate exactly one
00269    /// brick!  it will be padded to the right power of 2
00270 
00271    /// TODO: this is wrong, you need on voxel of overlap,
00272    ///  which we have, but, that means the remainder is wrong,
00273    ///  we loose a voxel off the end for each brick we have!
00274    unsigned int nxb = vsize.x/bdim.x;
00275    if(vsize.x%bdim.x) nxb += 1;
00276 
00277    unsigned int nyb = vsize.y/bdim.y;
00278    if(vsize.y%bdim.y) nyb += 1;
00279 
00280    unsigned int nzb = vsize.z/bdim.z;
00281    if(vsize.z%bdim.z) nzb += 1;
00282 
00283    vec3i pos(0,0,0);
00284    /// generate bricks along z
00285    for(unsigned int z=0; z<nzb; ++z, pos.z+=bdim.z-1)
00286    {
00287       pos.y = 0;
00288       /// generate bricks along y
00289       for(unsigned int y=0; y<nyb; ++y, pos.y+=bdim.y-1)
00290       {
00291          pos.x = 0;
00292          /// generate bricks along x
00293          for(unsigned int x=0; x<nxb; ++x, pos.x+=bdim.x-1)
00294          {
00295             NrroSP nnew;
00296             if(pos + bdim > vsize) /// we have a remainder
00297             {
00298                nnew = genBrick(pos, getNextPow2(vsize - pos), n);
00299             }
00300             else
00301             {
00302                nnew = genBrick(pos, bdim, n);
00303             }
00304             NrroSPVec::push_back(nnew);
00305             //cerr << "brick dims " << nnew->dim(0) << " " << nnew->dim(1) << " " << nnew->dim(2) << " " << nnew->dim(3) << endl;
00306          }
00307       }
00308    }
00309    setBricked(true);
00310 }
00311 
00312 ///////////////////////////////////////////////////////////////////////////
00313 ///////////////////////////////////////////////////////////////////////////
00314 ///////////////////////////////////////////////////////////////////////////
00315 ///////////////////////////////////////////////////////////////////////////
00316 /// VolFieldVec
00317 ///////////////////////////////////////////////////////////////////////////
00318 ///////////////////////////////////////////////////////////////////////////
00319 ///////////////////////////////////////////////////////////////////////////
00320 ///////////////////////////////////////////////////////////////////////////
00321 
00322 ///////////////////////////////////////////////////////////////////////////
00323 /// Update
00324 ///////////////////////////////////////////////////////////////////////////
00325 void VolFieldVec::update()
00326 {
00327    /// just call update on each of our children
00328    for(unsigned int i=0; i<size(); ++i)
00329    {
00330       if(!getField(i).isNull())
00331       {
00332          getField(i)->update();
00333       }
00334    }
00335 }
00336 
00337 bool VolFieldVec::needUpdate()
00338 {
00339    /// check if anyone needs an update
00340    bool ret = false;
00341    for(unsigned int i=0; i<size(); ++i)
00342    {
00343       if(!getField(i).isNull())
00344       {
00345          if(getField(i)->getUpdate()) ret = true;
00346       }
00347    }
00348    return ret;
00349 }
00350 
00351 ///////////////////////////////////////////////////////////////////////////
00352 /// Add Field
00353 ///////////////////////////////////////////////////////////////////////////
00354 void VolFieldVec::addNrro(NrroSP n)
00355 {
00356    n->forceMultiChannel();
00357    push_back(VolFieldSP(new VolField(n)));
00358 }
00359 
00360 
00361 ///////////////////////////////////////////////////////////////////////////
00362 /// Get Field
00363 ///////////////////////////////////////////////////////////////////////////
00364 VolFieldSP VolFieldVec::getField(unsigned int i)
00365 {
00366    if(i<size()) 
00367       return operator[](i);
00368 
00369    derr("getFields(), WARNING:: accessing a null field");
00370    return VolFieldSP(0);
00371 }
00372 
00373 
00374 ///////////////////////////////////////////////////////////////////////////
00375 /// Set Field
00376 ///////////////////////////////////////////////////////////////////////////
00377 void VolFieldVec::setField(unsigned int idx, VolField *f)
00378 {
00379    /// TODO: see if we can use vector::insert here
00380    for(unsigned int i=size()-1; i<idx; ++i)
00381    {
00382       operator[](i) = VolFieldSP();
00383    }
00384    operator[](idx) = VolFieldSP(f);
00385 }
00386 
00387 ///////////////////////////////////////////////////////////////////////////
00388 /// Delete Field
00389 ///////////////////////////////////////////////////////////////////////////
00390 void VolFieldVec::delField(unsigned int i)
00391 {
00392    /// TODO: Need to see if we can re-pack the fields
00393    /// TODO: See if vector::delete does the trick
00394    if(i<size())
00395       operator[](i) = VolFieldSP();
00396 }
00397 
00398 ///////////////////////////////////////////////////////////////////////////
00399 /// Check Fields
00400 ///////////////////////////////////////////////////////////////////////////
00401 bool VolFieldVec::checkFields()
00402 {
00403    bool bret = true;
00404    ///////////////////////////////////////////////////////////
00405    /// Check each fields for correctness:
00406    for(unsigned int i=0; i<size(); ++i)
00407    {
00408       VolFieldSP f = getField(i);
00409       if(!f.isNull())                  ///we have a field
00410          if(f->isActive())            ///it is active, otherwize ignore it
00411             if(!checkField(i))       ///make sure all is ready
00412                bret = false;        ///maybe it isn't
00413    }
00414    ///////////////////////////////////////////////////////////
00415 
00416    ///////////////////////////////////////////////////////////
00417    /// an all to all check
00418    /// need this because all we support right now are 
00419    /// equal sized bricks and textures
00420    /// TODO: handle unequal sized fields
00421    for(unsigned int i=0; i<size(); ++i)
00422    {
00423       /// we only check active fields
00424       if(getField(i)->isActive()) 
00425       {
00426          for(unsigned int k=i+1; k<size(); ++k)
00427          {      
00428             if(getField(k)->isActive())
00429             {
00430                if(!getField(i)->checkDims(getField(k)))
00431                {
00432                   bret = false;
00433                   /// this is a place to handle this sort of thing
00434                   derr("checkFields(), dims not matching");
00435                } 
00436             }/// if k is active
00437          }/// for k
00438       }/// if i is active
00439    }/// for i
00440 
00441    return bret;
00442 }
00443 
00444 
00445 ///////////////////////////////////////////////////////////////////////////
00446 /// check field
00447 ///////////////////////////////////////////////////////////////////////////
00448 /// I know this looks long, but it's mostly error checking!
00449 bool VolFieldVec::checkField(unsigned int i)
00450 {
00451    VolFieldSP f = getField(i);
00452    if(f.isNull())
00453    {
00454       /// this guy doesn't exist!
00455       derr("checkField(), null field");
00456       return false;
00457    }
00458 
00459    NrroSP n = f->getNrro();
00460    if(n.isNull())
00461    {
00462       /// this guy doesn't exist!
00463       derr("checkField(), null nrro");
00464       return false;
00465    }
00466 
00467    /// we can't handle anything but volumes and images right now
00468    if((Nrro::VOLUME != n->getKind()) && (Nrro::IMAGE != n->getKind()))
00469    {
00470       f->setActive(false);
00471       derr("checkField(), Nrro::KIND not supported");
00472       n->printKind();
00473       return false;
00474    }
00475 
00476    ////////////////////////////////////////////////////////
00477    /// this makes sure volumes are 4D and images are 3D
00478    if(((3==n->dim()) && (n->getKind() == Nrro::VOLUME)) ||
00479       ((2==n->dim()) && (n->getKind() == Nrro::IMAGE)))
00480    {
00481       derr("checkField(), forcing multi-channel");
00482       n->forceMultiChannel();
00483       f->setUpdate(true);
00484    }
00485    ///////////////////////////////////////////////////////
00486 
00487    /// we don't know how to handle things bigger than this,
00488    /// TODO: need a way to render time series volumes
00489    if(n->dim() > 4)
00490    {
00491       derr("checkField(), don't know how to handle volume with greater than 4 dims");
00492       f->setActive(false);
00493       return false;
00494    }
00495 
00496    /// check to see if we have more than 4 channels,
00497    /// if so we need to split them
00498    /// TODO: handle images the same way
00499    /// TODO: Maybe we shouldn't do this automatically?
00500    if((n->dim(0) > 4) && (n->getKind() == Nrro::VOLUME))
00501    {
00502       NrroSP n = f->getNrro();
00503       derr("checkField(), large number of fields, needs split");
00504       int lastField = 0;
00505       /// break out into sets of fields 4 or less
00506       while(n->dim(0) - lastField > 4)
00507       {
00508          int min[4] = {lastField, -1, -1, -1};
00509          int max[4] = {lastField+4, -1, -1, -1};
00510          max[0] = g_min(max[0], int(n->dim(0)-1));
00511          NrroSP nnew = n->crop(min, max);
00512          if(!nnew->isValid()) return false;
00513          VolFieldSP nvf(new VolField(nnew));
00514          nvf->setActive(f->isActive());
00515          push_back(nvf);
00516          lastField = max[0] + 1;
00517       }
00518       /// set this one inactive since
00519       /// we just generated a split up duplicate of it
00520       f->setActive(false);
00521       f->clearTex();
00522       f->nukeBricks();
00523    }
00524    return true;
00525 }
00526 
00527 ///////////////////////////////////////////////////////////////////////////
00528 /// BrickData
00529 ///////////////////////////////////////////////////////////////////////////
00530 void VolFieldVec::brickData(gutz::vec3i bdims)
00531 {
00532    ///TODO: Need to handle different resolution datasets somehow                
00533    /// hmm, really need to think that through
00534    for(unsigned int i=0; i<size(); ++i)
00535    {
00536       if((getField(i)->isActive()) &&       //active
00537          ( (!getField(i)->isBricked()) ||   //not bricked or...
00538          (getField(i)->getUpdate()) ) )   //something changed
00539       {
00540          getField(i)->clearTex();
00541          getField(i)->nukeBricks();
00542          getField(i)->brick(bdims);
00543       }
00544    }
00545 
00546 }       

Send questions, comments, and bug reports to:
jmk