00001 //------------------------------------------------------------------------ 00002 // 00003 // Joe Kniss 00004 // 3-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 // TFBase.h 00019 00020 // a base interface for transfer functions 00021 00022 #ifndef __SIMIAN_TRANSFER_FUNCTION_BASE_DOT_H 00023 #define __SIMIAN_TRANSFER_FUNCTION_BASE_DOT_H 00024 00025 #include <simBase/simBase.h> 00026 #include <volume/Volume.h> 00027 #include <smartptr.h> 00028 #include "TFParams.h" 00029 #include "TFElement.h" 00030 #include "TFImage.h" 00031 #include <nrro/nrro.h> 00032 00033 00034 ////////////////////////////////////////////////////////////////////////// 00035 /// a generic ND transfer function. 00036 /// Handles basic TFElement management and various TF generation 00037 /// methods. 00038 ////////////////////////////////////////////////////////////////////////// 00039 class TFGeneric : public SimBase, public gutz::Counted { 00040 public: 00041 typedef STF::tfDomainType PosType; 00042 typedef STF::tfRangeType ValType; 00043 00044 TFGeneric(); 00045 TFGeneric(VolumeSP vol); 00046 virtual ~TFGeneric(); 00047 00048 /////////////////////////////////////////// 00049 ///@name Evaluate 00050 /// Evaluate the transfer function at some arbitrary position 00051 ///@{ 00052 virtual ValType eval(const PosType &tfpos); 00053 ///@} 00054 00055 ////////////////////////////////////////////////////// 00056 ///@name Domain 00057 ///@{ 00058 00059 /////////////////////////////////////////// 00060 /// dimension of transfer function domain 00061 /// how many axies does the transfer function have??? 00062 virtual int sizeDomain() const { return 0;} 00063 00064 /////////////////////////////////////////// 00065 /// how many bins will discrete TF maps have? 00066 /// default is 256 for all TF domain axes. 00067 virtual PosType getDomainRes() const {return _res;} 00068 /// notice that you are passing a gutz::vec, so you 00069 /// can have a different number of bins for each axis 00070 virtual void setDomainRes(const PosType &res){_res = res;} 00071 00072 ///@} 00073 ////////////////////////////////////////////////////// 00074 00075 00076 /////////////////////////////////////////// 00077 ///@name Range 00078 /// dimension of transfer function range, 00079 /// ex. 4 is probably standard for RGBA output 00080 ///@{ 00081 virtual int sizeRange() const { return 0;} 00082 ///@} 00083 00084 /////////////////////////////////////////// 00085 ///@name Volume stuff 00086 ///@{ 00087 virtual void setVolume(VolumeSP v) { _vol = v; } 00088 virtual VolumeSP getVolume() const { return _vol;} 00089 ///@} 00090 00091 /////////////////////////////////////////// 00092 ///@name Transfer function elements 00093 ///@{ 00094 TFElementListSP getTFElts() const { return _elts; } 00095 void setTFElts(TFElementListSP _tfe) { _elts = _tfe;} 00096 void addTFElt(TFEltSP tfelt) { _elts->push_back(tfelt); } 00097 void addTFElement(TFElement *tfelt) { addTFElt( TFEltSP(tfelt) ); } 00098 ///@} 00099 00100 /////////////////////////////////////////// 00101 /// reimplemented from SimBase, needed since changes are dependent on 00102 /// sub-objects like TFElements 00103 virtual int getChangeID(); 00104 00105 //////////////////////////////////////////// 00106 /// Generate a 2D tf image (map) from a pair 00107 /// of axies (axiesIdx) of the tfdomain ... 00108 /// ... with some size, type, specific values in your choice of order, 00109 /// ... and your choice of how many values (channels) it should have 00110 /// kind is from STF::TF_4MAP_KINDS 00111 /// type is from Nrro::NRRO_TYPES 00112 //////////////////////////////////////////// 00113 TFImageSP get2DMap( 00114 gutz::vec2i axesIdx, /// idicies of domain axes 00115 const gutz::vec2i size = gutz::vec2i_neg_one, /// size of map 00116 int type = Nrro::UCHAR, /// what data type? 00117 int kind = STF::TF_RGBA); /// type of TFimage (which channels?) 00118 00119 protected: 00120 /////////////////////////////////////////// 00121 /// update the transfer function, checks to see if any of the elements 00122 /// changed and updates if it needs to. You can call this whenever you 00123 /// want. 00124 virtual void update(); 00125 00126 TFImageSP getImage(const gutz::vec2i &ai); 00127 void setImage(const TFImageSP im); 00128 00129 VolumeSP _vol; 00130 TFElementListSP _elts; 00131 00132 PosType _res; 00133 00134 /// cache generated tf images... 00135 TFImageSPMap _images; 00136 }; 00137 00138 typedef gutz::SmartPtr<TFGeneric> TFGenericSP; 00139 00140 ////////////////////////////////////////////////////////////////////////// 00141 //// a double indirection tf class so that you can dynamically change the 00142 //// tf and those changes will be reflected everywhere, 00143 //// holds an actual transfer function (one that implements the interface) 00144 //// allows you access to that guy. Unfortunately, you shouldn't copy 00145 //// this, you would have to make a specific sub class that knew what 00146 //// kind of tf actually implemented the interface; ie. copy won't copy 00147 //// the transfer function interface, just the pointer!!! 00148 //// 00149 //// If you use a transfer function somewhere use one of these and stay in 00150 //// synch with it, ie. assume it is volitle. If you implement a new TF type 00151 //// implement the TFBaseIF, so that users can plug it into one of these 00152 //// DO NOT Subclass this guy, only the (user) interface! 00153 //// TODO: should we rethink the name of this thing??? seems like we 00154 //// should be more expicit about the double indirection nature... 00155 /////////////////////////////////////////////////////////////////////////// 00156 class TFBaseSP : 00157 public gutz::SmartPtrRef<TFGeneric>, 00158 public SimBase 00159 { 00160 public: 00161 typedef gutz::SmartPtrRef<TFGeneric> btype; 00162 00163 TFBaseSP() 00164 : btype(new TFGeneric()), 00165 _lastChanged((*_ref)->getChangeID()) 00166 {} 00167 00168 TFBaseSP(VolumeSP vol) 00169 : btype(new TFGeneric(vol)), 00170 _lastChanged((*_ref)->getChangeID()) 00171 {} 00172 00173 TFBaseSP(TFGeneric *tf) 00174 : btype(tf), 00175 _lastChanged((*_ref)->getChangeID()) 00176 {} 00177 00178 ///we are not really a reference, we are a double indirection 00179 /// thingy, not really a pointer pointer, not really a ref either. 00180 /// this means that we have to copy the pointer inside the 00181 /// ref for copy and assignment so that changes are reflected 00182 /// everywhere. 00183 TFBaseSP(const TFBaseSP &tfbsp) : btype() 00184 { 00185 assign(const_cast<btype::type*>(tfbsp._ref)); 00186 _lastChanged = (*_ref)->getChangeID(); 00187 } 00188 00189 TFBaseSP &operator=(const TFBaseSP &tfbsp) 00190 { 00191 assign(const_cast<btype::type*>(tfbsp._ref)); 00192 setChanged(); 00193 _lastChanged = -1; 00194 return *this; 00195 } 00196 00197 virtual ~TFBaseSP() {} 00198 00199 /// if you are keeping track of changes yourself 00200 /// use this function, if you want to use this object 00201 /// as an observer, DO NOT use this one, use 00202 /// the functions below 00203 virtual int getChangeID() 00204 { 00205 if(_lastChanged != (*_ref)->getChangeID()) 00206 setChanged(); 00207 _lastChanged = (*_ref)->getChangeID(); 00208 return SimBase::getChangeID(); 00209 } 00210 00211 /// if you have one of thses objects, you don't need to 00212 /// keep track of the change id yourself. use these 00213 /// functions to see if the tf has changed since the last 00214 /// time you called "updateChanged()" 00215 bool tfChanged() const { return _lastChanged != (*_ref)->getChangeID(); } 00216 void updateChanged() { _lastChanged = (*_ref)->getChangeID(); } 00217 00218 protected: 00219 int _lastChanged; 00220 }; 00221 00222 #endif 00223