Katana Plug-in APIs 0.1

FnDataBuilder.h

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
 All Classes Functions Variables Typedefs Enumerations Enumerator