|
Katana Plug-in APIs 0.1
|
00001 // Copyright (c) 2011 The Foundry Visionmongers Ltd. All Rights Reserved. 00002 00003 #ifndef FoundryKatanaDataBuilder_H 00004 #define FoundryKatanaDataBuilder_H 00005 00006 #include <cstdint> 00007 #include <set> 00008 #include <stdexcept> 00009 #include <string> 00010 #include <map> 00011 #include <vector> 00012 00013 #include "FnAttribute/FnAttribute.h" 00014 #include "FnAttribute/FnAttributeAPI.h" 00015 #include "FnAttribute/ns.h" 00016 00017 FNATTRIBUTE_NAMESPACE_ENTER 00018 { 00019 00030 template<class ATTR> class DataBuilder { 00031 public: 00035 DataBuilder( int64_t tupleSize = 1) : _tupleSize(tupleSize) {} 00036 00040 DataBuilder( ATTR attr ); 00041 00045 void reserve(int64_t timeSampleDataCount, float timeSample = 0.f); 00046 00050 int64_t getTupleSize() const; 00051 00055 std::vector<float> getTimeSamples() const; 00056 00060 std::vector<typename ATTR::value_type>& get(const float timeSample = 0.f); 00061 00065 void set(const std::vector<typename ATTR::value_type>& timeSampleData, const float timeSample = 0.f); 00066 00070 void del(const float timeSample = 0.f); 00071 00075 void push_back( typename ATTR::value_type data, float timeSample = 0.f); 00076 00080 void update(ATTR &attr); 00081 00085 ATTR build(); 00086 00087 private: 00088 typedef ConstVector<typename ATTR::value_type> DataConstVector; 00089 typedef typename DataConstVector::const_iterator DataConstVectorItereator; 00090 00091 typedef std::map<float,std::vector<typename ATTR::value_type> > datacontainer; 00092 typedef typename datacontainer::iterator dataiterator; 00093 typedef typename datacontainer::const_iterator dataconstiterator; 00094 00095 datacontainer _data; 00096 00097 int64_t _tupleSize; 00098 }; 00099 00101 00102 template<class ATTR> DataBuilder<ATTR>::DataBuilder( ATTR attr ) 00103 { 00104 update( attr ); 00105 } 00106 00107 template<class ATTR> void DataBuilder<ATTR>::reserve(int64_t timeSampleDataCount, float timeSample) 00108 { 00109 _data[timeSample].reserve(timeSampleDataCount); 00110 } 00111 00112 template<class ATTR> int64_t DataBuilder<ATTR>::getTupleSize() const 00113 { 00114 return _tupleSize; 00115 } 00116 00117 template<class ATTR> std::vector<float> DataBuilder<ATTR>::getTimeSamples() const 00118 { 00119 std::vector<float> timeSample; 00120 for ( dataconstiterator iter = _data.begin(); iter != _data.end(); iter++) 00121 { 00122 timeSample.push_back( iter->first ); 00123 } 00124 return timeSample; 00125 } 00126 00127 template<class ATTR> std::vector<typename ATTR::value_type>& DataBuilder<ATTR>::get(const float timeSample) 00128 { 00129 return _data[timeSample]; 00130 } 00131 00132 template<class ATTR> void DataBuilder<ATTR>::set(const std::vector<typename ATTR::value_type>& timeSampleData,const float timeSample) 00133 { 00134 _data[timeSample] = timeSampleData; 00135 } 00136 00137 template<class ATTR> void DataBuilder<ATTR>::del(const float timeSample) 00138 { 00139 _data.erase( timeSample ); 00140 } 00141 00142 template<class ATTR> void DataBuilder<ATTR>::push_back( typename ATTR::value_type data, float timeSample) 00143 { 00144 _data[timeSample].push_back(data); 00145 } 00146 00147 template<class ATTR> ATTR DataBuilder<ATTR>::build() 00148 { 00149 // Otherwise handle regular attributes 00150 if ( _data.size() == 0 ) 00151 { 00152 // Return an attribute representing an empty array of the given 00153 // tuple size 00154 return ATTR(0x0, 0, _tupleSize); 00155 } 00156 00157 std::vector<float> timeSample; 00158 std::vector<const typename ATTR::value_type*> timeSampleData; 00159 size_t timeSampleDataCount = _data.begin()->second.size(); 00160 for ( dataiterator iter = _data.begin(); iter != _data.end(); iter++) 00161 { 00162 timeSample.push_back( iter->first ); 00163 timeSampleData.push_back( iter->second.data() ); 00164 // Time-sampled data must all be of the same size 00165 if ( timeSampleDataCount != iter->second.size() ) 00166 { 00167 throw std::runtime_error("Error building attribute time samples are different sizes."); 00168 } 00169 } 00170 00171 return ATTR( timeSample.data(), 00172 (int64_t) timeSample.size(), 00173 (const typename ATTR::value_type **) timeSampleData.data(), 00174 (int64_t) timeSampleDataCount, (int64_t) _tupleSize); 00175 } 00176 00177 template<class ATTR> void DataBuilder<ATTR>::update(ATTR &attr) 00178 { 00179 const int64_t numTimeSamples = attr.getNumberOfTimeSamples(); 00180 for (int sampleTimeIdx = 0; sampleTimeIdx < numTimeSamples; 00181 ++sampleTimeIdx) 00182 { 00183 float sampleTime = attr.getSampleTime(sampleTimeIdx); 00184 typename ATTR::array_type currentData = 00185 attr.getNearestSample(sampleTime); 00186 _data[sampleTime] = std::vector<typename ATTR::value_type>( 00187 currentData.begin(), currentData.end()); 00188 } 00189 _tupleSize = attr.getTupleSize(); 00190 } 00191 00193 00194 00195 typedef DataBuilder<IntAttribute> IntBuilder; 00196 typedef DataBuilder<FloatAttribute> FloatBuilder; 00197 typedef DataBuilder<DoubleAttribute> DoubleBuilder; 00198 00199 // StringBuilder is typically not recommended for use. 00200 // As strings are not generally multisampled, a builder is not appropriate. 00201 // (or efficient) If you'd like the convenience of array initialization, 00202 // consider using the std::vector<std::string> constructor directly. 00203 00204 typedef DataBuilder<StringAttribute> StringBuilder; 00205 00207 template<> 00208 FNATTRIBUTE_API StringAttribute DataBuilder<StringAttribute>::build(); 00209 // This makes it convenient to construct a StringAttr where the entries 00210 // are unique 00212 00213 class UniqueStringBuilder 00214 { 00215 private: 00216 std::vector<StringAttribute> attrs; 00217 00218 public: 00219 UniqueStringBuilder() 00220 { 00221 } 00222 00223 void add(const StringAttribute & attr) 00224 { 00225 if (!attr.isValid()) return; 00226 // This catches the case where you add a bunch of 00227 // the same stringattrs together in a row 00228 if (attrs.size()>0 && 00229 (attr.getHash() == attrs[attrs.size()-1].getHash())) return; 00230 attrs.push_back(attr); 00231 } 00232 00233 StringAttribute build() 00234 { 00235 if (attrs.empty()) 00236 { 00237 return StringAttribute(); 00238 } 00239 00240 if (attrs.size() == 1) 00241 { 00242 return attrs[0]; 00243 } 00244 00245 std::set<std::string> usedValues; 00246 std::vector<std::string> newValues; 00247 00248 for (std::vector<StringAttribute>::iterator I = attrs.begin(); 00249 I != attrs.end(); ++I) 00250 { 00251 StringAttribute::array_type values = (*I).getNearestSample(0); 00252 00253 for (StringAttribute::array_type::const_iterator vI = 00254 values.begin(), vE = values.end(); vI != vE; ++vI) 00255 { 00256 std::string value(*vI); 00257 00258 if (usedValues.find(value) == usedValues.end()) 00259 { 00260 usedValues.insert(value); 00261 newValues.push_back(value); 00262 } 00263 } 00264 } 00265 00266 if (!newValues.empty()) 00267 { 00268 return StringAttribute(newValues); 00269 } 00270 return StringAttribute(); 00271 } 00272 }; 00273 } 00274 FNATTRIBUTE_NAMESPACE_EXIT 00275 00276 #endif // FoundryKatanaDataBuilder_H
1.7.3