Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

General/vuTFunc/vuTFDesign.cpp

Go to the documentation of this file.
00001 #include <stdio.h>
00002 #include <iostream>
00003 #include "vuTFDesign.h"
00004 #include "vuColour31a.h"
00005 
00006 //----------------------------------------------------------------------------
00007 //------------------------- The default constructor --------------------------
00008 //----------------------------------------------------------------------------
00009 
00010 vuTFDesign::vuTFDesign(dword ncomp, 
00011                        dword range) : vuTFIntensity(ncomp,range)
00012 {
00013     //Add the essential nodes.
00014     m_Opacities.add(OpacityNode(0,0));
00015     m_Opacities.add(OpacityNode(255,0));
00016     m_Colours.add(ColourNode(255, m_NComp, (float)0));
00017 
00018     //Set the default smoothing
00019     m_OpacitySmoothing = 0;
00020     m_ColourSmoothing = 0;
00021     generateFunction();
00022 }
00023 
00024 //----------------------------------------------------------------------------
00025 //------------------------- public addOpacity() ------------------------------
00026 //----------------------------------------------------------------------------
00027 
00028 dword vuTFDesign::addOpacity(byte intensity, float opacity)
00029 {
00030     //Find where to insert the Opacity node
00031     dword l = m_Opacities.getLength();
00032     dword i = 0;
00033     for (i=0; i < l; i++)
00034         if (m_Opacities[i].intensity >= intensity) break;
00035 
00036     //Add the new Opacity node.
00037     if ((i < l) && m_Opacities[i].intensity==intensity)
00038         m_Opacities[i].opacity = opacity;
00039     else
00040         m_Opacities.insert(i,OpacityNode(intensity,opacity));
00041 
00042     return i;
00043 }
00044 
00045 //----------------------------------------------------------------------------
00046 //------------------------- public removeOpacity() ---------------------------
00047 //----------------------------------------------------------------------------
00048 
00049 void vuTFDesign::removeOpacity(dword index)
00050 {
00051     //Never delete the two Opacity nodes at the end
00052     if (index == 0 || index >= m_Opacities.getLength()-1) return;
00053 
00054     //Remove the Opacity node
00055     m_Opacities.remove(index);
00056 }
00057 
00058 //----------------------------------------------------------------------------
00059 //------------------------- public getNumOpacities() -------------------------
00060 //----------------------------------------------------------------------------
00061 
00062 dword vuTFDesign::getNumOpacities() const
00063 {
00064     return m_Opacities.getLength();
00065 }
00066 
00067 //----------------------------------------------------------------------------
00068 //------------------------- public getOpacity() ------------------------------
00069 //----------------------------------------------------------------------------
00070 
00071 const vuTFDesign::OpacityNode& vuTFDesign::getOpacity(dword index) const
00072 {
00073     return m_Opacities[index];
00074 }
00075 
00076 //----------------------------------------------------------------------------
00077 //----------------------------------------------------------------------------
00078 void vuTFDesign::clearAllNodes()
00079 {
00080   m_Opacities.removeRange(0,m_Opacities.getLength());
00081   m_Colours.removeRange(0,m_Colours.getLength());
00082   
00083   //Add the essential nodes.
00084   m_Opacities.add(OpacityNode(0,0));
00085   m_Opacities.add(OpacityNode(m_Range-1,0));
00086   m_Colours.add(ColourNode(m_Range-1, m_NComp, (float)0));
00087   
00088   //Set the default smoothing
00089   m_OpacitySmoothing = 0;
00090   m_ColourSmoothing = 0;
00091 }
00092 
00093 //----------------------------------------------------------------------------
00094 //------------------------- public getOpacitySmoothing() ---------------------
00095 //----------------------------------------------------------------------------
00096 
00097 float vuTFDesign::getOpacitySmoothing() const
00098 {
00099     return m_OpacitySmoothing;
00100 }
00101 
00102 //----------------------------------------------------------------------------
00103 //------------------------- public setOpacitySmoothing() ---------------------
00104 //----------------------------------------------------------------------------
00105 
00106 void vuTFDesign::setOpacitySmoothing(float val)
00107 {
00108     if (val > 1) val = 1;
00109     if (val < 0) val = 0;
00110     m_OpacitySmoothing = val;
00111 }
00112 
00113 //----------------------------------------------------------------------------
00114 //------------------------- public addColour() -------------------------------
00115 //----------------------------------------------------------------------------
00116 
00117 dword vuTFDesign::addColour(dword intensity, const vuColourN& _col)
00118 {
00119     //Check if this overwrites any other colours
00120     dword l = m_Colours.getLength();
00121     dword i = 0;
00122     for (i = 0; i < l; i++)
00123         if (m_Colours[i].intensity >= intensity) break;
00124 
00125     //Create the colour node
00126     ColourNode cp(intensity,m_NComp,_col);
00127 
00128     //Add the new colour node.
00129     if ((i < l) && m_Colours[i].intensity==intensity)
00130         m_Colours[i] = cp;
00131     else
00132         m_Colours.insert(i,cp);
00133 
00134     return i;
00135 }
00136 
00137 //----------------------------------------------------------------------------
00138 //------------------------- public addColour() -------------------------------
00139 //----------------------------------------------------------------------------
00140 
00141 dword vuTFDesign::addColour(dword intensity, const float* _col)
00142 {
00143     //Check if this overwrites any other colours
00144     dword l = m_Colours.getLength();
00145     dword i = 0;
00146     for (i = 0; i < l; i++)
00147         if (m_Colours[i].intensity >= intensity) break;
00148 
00149     //Create the colour node
00150     ColourNode cp(intensity,m_NComp,_col);
00151 
00152     //Add the new colour node.
00153     if ((i < l) && m_Colours[i].intensity==intensity)
00154         m_Colours[i] = cp;
00155     else
00156         m_Colours.insert(i,cp);
00157 
00158     return i;
00159 }
00160 
00161 //----------------------------------------------------------------------------
00162 //------------------------- public removeColour() ----------------------------
00163 //----------------------------------------------------------------------------
00164 
00165 void vuTFDesign::removeColour(dword index)
00166 {
00167     //Never delete the colour node at the end
00168     if (index >= m_Colours.getLength() - 1) return;
00169 
00170     //Remove the colour node.
00171     m_Colours.remove(index);
00172 }
00173 
00174 //----------------------------------------------------------------------------
00175 //------------------------- public getNumColours -----------------------------
00176 //----------------------------------------------------------------------------
00177 
00178 dword vuTFDesign::getNumColours() const
00179 {
00180     return m_Colours.getLength();
00181 }
00182 
00183 dword vuTFDesign::getColourNodeIndex(const ColourNode& cnode) const
00184 {
00185     dword i=0;          // we have to search for the index :-|
00186     while(m_Colours[i].intensity<cnode.intensity) i++;
00187     return i;
00188 }
00189 
00190 //----------------------------------------------------------------------------
00191 //------------------------- public getColour() -------------------------------
00192 //----------------------------------------------------------------------------
00193 
00194 const vuTFDesign::ColourNode& vuTFDesign::getColour(dword index) const
00195 {
00196     return m_Colours[index];
00197 }
00198 
00199 
00200 //----------------------------------------------------------------------------
00201 //------------------------- public getColourSmoothing() ----------------------
00202 //----------------------------------------------------------------------------
00203 
00204 float vuTFDesign::getColourSmoothing() const
00205 {
00206     return m_ColourSmoothing;
00207 }
00208 
00209 
00210 //----------------------------------------------------------------------------
00211 //------------------------- public setColourSmoothing() ----------------------
00212 //----------------------------------------------------------------------------
00213 
00214 void vuTFDesign::setColourSmoothing(float val)
00215 {
00216     if (val > 1) val = 1;
00217     if (val < 0) val = 0;
00218     m_ColourSmoothing = val;
00219 }
00220 
00221 //----------------------------------------------------------------------------
00222 //------------------------- public generateFunction() ------------------------
00223 //----------------------------------------------------------------------------
00224 
00225 void vuTFDesign::generateFunction()
00226 {
00227     dword index;
00228     dword numColours = m_Colours.getLength();
00229     generateOpacities();
00230     
00231     //Set up the array representing the colour functions
00232     //Note that we always have at least one colour Node
00233     index = 0;
00234     for (dword i = 0; i < numColours; i++)
00235     {
00236         for (; index <= m_Colours[i].intensity; index ++)
00237         {
00238           dword cind = index*m_NComp;
00239           for(dword c=0;c<m_NComp-1;c++) {
00240             m_Table[cind+c] = m_Colours[i].col[c];
00241           }
00242         }
00243     }
00244 
00245     //Apply the smoothing functions, if any, to the functions
00246     smooth(&m_Table[m_NComp-1], m_OpacitySmoothing);
00247     for(dword c=0;c<m_NComp-1;c++) {
00248       smooth(&m_Table[c], m_ColourSmoothing);
00249     }
00250 
00251 }
00252 
00253 //----------------------------------------------------------------------------
00254 void vuTFDesign::generateOpacities()
00255 {
00256     dword index;
00257     dword numOpacities = m_Opacities.getLength();
00258 //    dword numColours = m_Colours.getLength();
00259     //First set up the arrays representing the intensity function
00260     //Note that we always have at least two Nodes
00261     index = 0;
00262     for (dword i = 0; i < numOpacities-1; i++)
00263     {
00264         float slope = float(m_Opacities[i+1].opacity - m_Opacities[i].opacity)/
00265             float(m_Opacities[i+1].intensity - m_Opacities[i].intensity);
00266         
00267         for (; index <= m_Opacities[i+1].intensity; index ++)
00268             m_Table[index*m_NComp+(m_NComp-1)] = m_Opacities[i].opacity +
00269                 slope * (index-m_Opacities[i].intensity);
00270     }
00271 }
00272 
00273 
00274 //----------------------------------------------------------------------------
00275 //------------------------- private smooth() ---------------------------------
00276 //----------------------------------------------------------------------------
00277 
00278 void vuTFDesign::smooth(float *data,float percent) const
00279 {
00280     const int num = (int)m_Range;
00281 
00282     float *in = new float[num];
00283     
00284     //Smooth the function using a low pass filter, achieved by averaging.
00285 
00286     //Copy the data.
00287     for (int i = 0, index = 0; i < num; i++, index+=m_NComp)
00288         in[i] = data[index];
00289 
00290     //Average it out
00291     if (percent < 0) percent = 0;
00292     if (percent > 1) percent = 1;
00293     int offset = (int)(num * percent / 2);
00294     for (int i = 0, index = 0; i < num; i++, index+=m_NComp)
00295     {
00296         data[index] = 0;
00297         for (int j = i-offset; j <= i + offset; j++)
00298         {
00299             if (j >= 0)
00300             {
00301                 if(j < num)
00302                     data[index] += in[j];
00303                 else data[index] += in[num-1];
00304             } else data[index] += in[0];
00305         }
00306         data[index] /= (offset*2 + 1);
00307     }
00308     delete [] in;
00309 }
00310 
00311 //----------------------------------------------------------------------------
00312 bool vuTFDesign::loadTF(const char* fname)
00313 {
00314   try {
00315     Parse(fname);
00316   } catch(const char *msg) {
00317     cout << msg << endl;
00318     return false;
00319   }
00320   return true;
00321 }
00322 
00323 //----------------------------------------------------------------------------
00324 bool vuTFDesign::saveTF(const char* fname) const
00325 {
00326   ofstream ofp;
00327   ofp.open(fname, ios::out);
00328 
00329   writeTFunc(ofp);
00330   
00331   return true;
00332 }
00333 
00334 void vuTFDesign::writeTFunc(ofstream &ofp) const
00335 {
00336     writeNComp(ofp);
00337     writeOpacities(ofp);
00338     writeColours(ofp);
00339 }
00340 
00341 bool vuTFDesign::writeNComp(ofstream &ofp) const
00342 {
00343     ofp << "components("<< m_NComp-1 << ")" << endl;
00344     return true;
00345 }
00346 
00347 bool vuTFDesign::readNComp()
00348 {
00349     if(readString("components")) {
00350         float ncomp;
00351         if(!readNumber(" ( ", ncomp)) throw "Error reading number of components.";
00352         else readString(" ) ");
00353         if(m_NComp != ncomp+1) {
00354             m_NComp = int(ncomp)+1;             // add alpha channel
00355             cout<<"Changing transfer function format to "<<m_NComp-1<<"+1 components."<<endl;
00356             init(m_NComp,m_Range);
00357         }
00358         return true;
00359     } else return false;
00360 }
00361 
00362 bool vuTFDesign::writeOpacities(ofstream &ofp) const
00363 {
00364     //opacities
00365     dword nopa = getNumOpacities();
00366     for(dword o=0;o<nopa;o++) {
00367         ofp<<"opacity("<<getOpacity(o).intensity<<", "<<getOpacity(o).opacity<<")"<<endl;
00368     }
00369     ofp<<endl;
00370     return true;
00371 }
00372 
00373 bool vuTFDesign::writeColours(ofstream &ofp) const
00374 {
00375   //colours
00376   dword ncol = getNumColours();
00377   for(dword o=0;o<ncol;o++) {
00378     ofp<<"colour("<<getColour(o).intensity;
00379     for(dword c=0;c<m_NComp;c++)
00380       ofp<<", "<<getColour(o).col[c];
00381     ofp<<")"<<endl<<endl;
00382   }
00383   ofp<<endl;
00384   return true;
00385 }
00386 
00387 //----------------------------------------------------------------------------
00388 //------------------------- ColourNode constructor ---------------------------
00389 //----------------------------------------------------------------------------
00390 
00391 vuTFDesign::ColourNode::ColourNode(byte inten, dword ncomp, const vuColourN& _col)
00392 {
00393     intensity = inten;
00394     if((dword)_col.nComponents() == ncomp) {
00395       for(dword c=0;c<ncomp;c++) {
00396         col[c] = _col[c];
00397       }
00398     }
00399 }
00400 
00401 //----------------------------------------------------------------------------
00402 //------------------------- ColourNode constructor ---------------------------
00403 //----------------------------------------------------------------------------
00404 
00405 vuTFDesign::ColourNode::ColourNode(byte inten, dword ncomp, const float* _col)
00406 {
00407     intensity = inten;
00408     for(dword c=0;c<ncomp;c++) {
00409       col[c] = _col[c];
00410     }
00411 }
00412 
00413 //----------------------------------------------------------------------------
00414 //------------------------- ColourNode constructor ---------------------------
00415 //----------------------------------------------------------------------------
00416 
00417 vuTFDesign::ColourNode::ColourNode(byte inten, dword ncomp, float val)
00418 {
00419     intensity = inten;
00420 
00421     for(dword c=0;c<ncomp;c++)
00422       col[c] = val;
00423 }
00424 
00425 //----------------------------------------------------------------------------
00426 // functions for the parser
00427 //----------------------------------------------------------------------------
00428 void vuTFDesign::Parse(const char* filename) throw (const char *)
00429 {
00430   readBuffer(filename);
00431   FixBuffer();
00432   parseTFunc();
00433 }
00434 
00435 void vuTFDesign::parseTFunc()
00436 {
00437   clearAllNodes();
00438 
00439   bool read = true;
00440   while (read) {
00441       read = false;
00442       if ( readOpacity() ) { read = true; }
00443       else if ( readColour() ) { read = true; }
00444       else if ( readNComp() ) { read = true; };
00445   }
00446 }
00447 
00448 bool vuTFDesign::readColour()
00449 {
00450   if( readString("colour") ) {
00451     float intensity;
00452     float col[32];
00453     if(!readNumber(" ( ",intensity)) throw "Error reading colour.";
00454     bool read = true;
00455     dword c = 0;
00456     while (read && c<32) {
00457       read = false;
00458       if(readNumber(" , ",col[c])) {
00459         read = true;
00460         c++;
00461       } else if(readString(" ) ")) read = false;
00462     }
00463     if(c==32) readString(" ) ");
00464     else if(c==0) throw "Error reading colour components";
00465     while(c<32) col[c++] = 0.0f;
00466     addColour((dword)intensity,col);
00467     return true;
00468   } else return false;
00469 }
00470 
00471 bool vuTFDesign::readOpacity()
00472 {
00473   if( readString("opacity") ) {
00474     float intensity;
00475     float opa;
00476     if(readNumber(" ( ",intensity) &&
00477        readNumber(" , ",opa) && 
00478        readString(" ) ")) {
00479       addOpacity((dword)intensity,opa);
00480       return true;
00481     } else throw "Error reading opacity.";
00482   } else return false;
00483 }
00484 

Generated on Wed Dec 15 21:20:38 2004 for vuVolume by  doxygen 1.3.9.1