Field3D
Field.h
Go to the documentation of this file.
00001 //----------------------------------------------------------------------------//
00002 
00003 /*
00004  * Copyright (c) 2009 Sony Pictures Imageworks Inc
00005  *
00006  * All rights reserved.
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted provided that the following conditions
00010  * are met:
00011  *
00012  * Redistributions of source code must retain the above copyright
00013  * notice, this list of conditions and the following disclaimer.
00014  * Redistributions in binary form must reproduce the above copyright
00015  * notice, this list of conditions and the following disclaimer in the
00016  * documentation and/or other materials provided with the
00017  * distribution.  Neither the name of Sony Pictures Imageworks nor the
00018  * names of its contributors may be used to endorse or promote
00019  * products derived from this software without specific prior written
00020  * permission.
00021  *
00022  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00023  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00024  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00025  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
00026  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00027  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00028  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00029  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00030  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
00031  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00032  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
00033  * OF THE POSSIBILITY OF SUCH DAMAGE.
00034  */
00035 
00036 //----------------------------------------------------------------------------//
00037 
00043 //----------------------------------------------------------------------------//
00044 
00045 #ifndef _INCLUDED_Field3D_Field_H_
00046 #define _INCLUDED_Field3D_Field_H_
00047 
00048 #include <cmath>
00049 #include <vector>
00050 #include <map>
00051 
00052 #include <boost/intrusive_ptr.hpp> 
00053 #include <boost/thread/mutex.hpp>
00054 
00055 #include "Traits.h"
00056 #include "Exception.h"
00057 #include "FieldMapping.h"
00058 #include "FieldMetadata.h"
00059 #include "Log.h"
00060 #include "RefCount.h"
00061 #include "Types.h"
00062 
00063 //----------------------------------------------------------------------------//
00064 
00065 #include "ns.h"
00066 
00067 FIELD3D_NAMESPACE_OPEN
00068 
00069 //----------------------------------------------------------------------------//
00070 // Exceptions
00071 //----------------------------------------------------------------------------//
00072 
00073 namespace Exc {
00074 
00075 DECLARE_FIELD3D_GENERIC_EXCEPTION(MemoryException, Exception)
00076 DECLARE_FIELD3D_GENERIC_EXCEPTION(ResizeException, Exception)
00077 
00078 } // namespace Exc
00079 
00080 //----------------------------------------------------------------------------//
00081 // FieldBase
00082 //----------------------------------------------------------------------------//
00083 
00091 class FieldBase : public RefBase
00092 {
00093 public:
00094 
00095   // Typedefs ------------------------------------------------------------------
00096 
00097   typedef boost::intrusive_ptr<FieldBase> Ptr;
00098   typedef FieldBase class_type;
00099 
00100   // Constructors --------------------------------------------------------------
00101 
00104 
00106   FieldBase();
00107 
00109   FieldBase(const FieldBase &);
00110 
00112   virtual ~FieldBase();
00113 
00115 
00116   // RTTI replacement ----------------------------------------------------------
00117 
00118   static const char *staticClassName()
00119   {
00120     return "FieldBase";
00121   }
00122 
00123   static const char* classType()
00124   {
00125     return staticClassName();
00126   }
00127   
00128   // To be implemented by subclasses -------------------------------------------
00129 
00132 
00138   virtual std::string className() const = 0;
00139 
00142   virtual Ptr clone() const = 0;
00143 
00145 
00146   // Access to metadata --------------------------------------------------------
00147 
00150 
00152   FieldMetadata<FieldBase>& metadata()
00153   { return m_metadata; }
00154 
00156   const FieldMetadata<FieldBase>& metadata() const
00157   { return m_metadata; }
00158 
00161   virtual void metadataHasChanged(const std::string &/* name */) 
00162   { /* Empty */ }
00163 
00165   void copyMetadata(const FieldBase &field)
00166   { m_metadata = field.metadata(); }
00167 
00169 
00170   // Public data members -------------------------------------------------------
00171 
00173   std::string name;
00175   std::string attribute;
00176 
00177  private:
00178 
00179   // Private data members ------------------------------------------------------
00180 
00182   FieldMetadata<FieldBase> m_metadata;
00183 
00184 };
00185 
00186 //----------------------------------------------------------------------------//
00187 // FieldRes
00188 //----------------------------------------------------------------------------//
00189 
00207 //----------------------------------------------------------------------------//
00208 
00209 class FieldRes : public FieldBase
00210 {
00211 public:
00212 
00213   // Typedefs ------------------------------------------------------------------
00214 
00215   typedef boost::intrusive_ptr<FieldRes> Ptr;
00216   typedef std::vector<Ptr> Vec;
00217 
00218   // RTTI replacement ----------------------------------------------------------
00219 
00220   typedef FieldRes class_type;
00221   DEFINE_FIELD_RTTI_ABSTRACT_CLASS;
00222 
00223   virtual std::string dataTypeString() const
00224     { return std::string("FieldRes"); }
00225 
00226   static const char *staticClassName()
00227   {
00228     return "FieldRes";
00229   }
00230 
00231   static const char *classType()
00232   {
00233     return staticClassName();
00234   }
00235   
00236   // Ctor, dtor ----------------------------------------------------------------
00237 
00239   FieldRes();
00240 
00243   FieldRes(const FieldRes &src);
00244 
00245   // Main methods --------------------------------------------------------------
00246 
00251   inline const Box3i& extents() const
00252   { return m_extents; }
00255   inline const Box3i& dataWindow() const
00256   { return m_dataWindow; }
00257 
00258   inline V3i const dataResolution() const
00259   { return m_dataWindow.max - m_dataWindow.min + V3i(1); }
00260 
00262   void setMapping(FieldMapping::Ptr mapping);
00263 
00265   FieldMapping::Ptr mapping()
00266   { return m_mapping; }
00267 
00269   const FieldMapping::Ptr mapping() const
00270   { return m_mapping; }
00271 
00273   bool isInBounds(int i, int j, int k) const;
00274 
00275   // To be implemented by subclasses -------------------------------------------
00276 
00281   virtual long long int memSize() const
00282   { return sizeof(*this); }
00283 
00284 protected:
00285 
00286   // Typedefs ------------------------------------------------------------------
00287 
00288   typedef MatrixFieldMapping default_mapping;
00289 
00290   // Data members --------------------------------------------------------------
00291 
00296   Box3i m_extents;
00299   Box3i m_dataWindow;
00301   FieldMapping::Ptr m_mapping;
00302 
00303 private:
00304 
00305   // Typedefs ------------------------------------------------------------------
00306 
00308   typedef FieldBase base;
00309 
00310 };
00311 
00312 //----------------------------------------------------------------------------//
00313 
00314 inline FieldRes::FieldRes()
00315   : m_mapping(new default_mapping)
00316 { 
00317   m_extents = Box3i(V3i(0), V3i(-1));
00318   m_dataWindow = m_extents;
00319   m_mapping->setExtents(m_extents); 
00320 }
00321 
00322 //----------------------------------------------------------------------------//
00323 
00324 inline FieldRes::FieldRes(const FieldRes &src) 
00325   : FieldBase(src)
00326 {
00327   // Call base class first
00328   // FieldBase(src);
00329   // Copy self
00330   *this = src;
00331   m_mapping = src.mapping()->clone();
00332 }
00333 
00334 //----------------------------------------------------------------------------//
00335 
00336 inline void FieldRes::setMapping(FieldMapping::Ptr mapping)
00337 { 
00338   if (mapping) {
00339     m_mapping = mapping->clone(); 
00340     m_mapping->setExtents(m_extents); 
00341   } else {
00342     Msg::print(Msg::SevWarning, 
00343                "Tried to call FieldRes::setMapping with null pointer");
00344   }
00345 }
00346 
00347 //----------------------------------------------------------------------------//
00348 
00349 inline bool FieldRes::isInBounds(int i, int j, int k) const
00350 {
00351   // Check bounds
00352   if (i < m_dataWindow.min.x || i > m_dataWindow.max.x ||
00353       j < m_dataWindow.min.y || j > m_dataWindow.max.y ||
00354       k < m_dataWindow.min.z || k > m_dataWindow.max.z) {
00355     return false;
00356   }
00357 
00358   return true;
00359 }
00360 
00361 //----------------------------------------------------------------------------//
00362 // Field
00363 //----------------------------------------------------------------------------//
00364 
00375 template <class Data_T>
00376 class Field : public FieldRes
00377 {
00378 public:
00379 
00380   // Typedefs ------------------------------------------------------------------
00381   
00382   typedef boost::intrusive_ptr<Field> Ptr;
00383 
00385   typedef Data_T value_type;
00386 
00390   typedef std::vector<Ptr> Vec;
00391 
00392   // RTTI replacement ----------------------------------------------------------
00393 
00394   typedef Field<Data_T> class_type;
00395   DEFINE_FIELD_RTTI_ABSTRACT_CLASS;
00396 
00397   static const char *staticClassName()
00398   {
00399     return "Field";
00400   }
00401 
00402   static const char* classType()
00403   {
00404     return Field<Data_T>::ms_classType.name();
00405   }
00406 
00407   // Constructors --------------------------------------------------------------
00408 
00410   virtual ~Field()
00411   { /* Empty */ }
00412 
00413   // Iterators -----------------------------------------------------------------
00414 
00417   class const_iterator;
00418 
00420   const_iterator cbegin() const;
00422   const_iterator cbegin(const Box3i &subset) const;
00424   const_iterator cend() const;
00427   const_iterator cend(const Box3i &subset) const;
00428 
00429   // To be implemented by subclasses -------------------------------------------
00430 
00437   virtual Data_T value(int i, int j, int k) const = 0;
00438 
00439   // Other member functions ----------------------------------------------------
00440 
00441   virtual std::string dataTypeString() const 
00442   { return DataTypeTraits<Data_T>::name(); }
00443 
00444 
00445 private:
00446 
00447   // Static data members -------------------------------------------------------
00448 
00449   static TemplatedFieldType<Field<Data_T> > ms_classType;
00450 
00451   // Typedefs ------------------------------------------------------------------
00452 
00454   typedef FieldRes base;
00455 
00456 };
00457 
00458 //----------------------------------------------------------------------------//
00459 
00460 #define FIELD3D_CLASSTYPE_TEMPL_INSTANTIATION(field)                  \
00461   template <typename Data_T>                                          \
00462   TemplatedFieldType<field<Data_T> > field<Data_T>::ms_classType =    \
00463     TemplatedFieldType<field<Data_T> >();                             \
00464   
00465 FIELD3D_CLASSTYPE_TEMPL_INSTANTIATION(Field);
00466 
00467 //----------------------------------------------------------------------------//
00468 
00469 template <class Data_T> 
00470 typename Field<Data_T>::const_iterator 
00471 Field<Data_T>::cbegin() const
00472 {
00473   if (FieldRes::dataResolution() == V3i(0))
00474     return cend();
00475   return const_iterator(*this, m_dataWindow, m_dataWindow.min);
00476 }
00477 
00478 //----------------------------------------------------------------------------//
00479 
00480 template <class Data_T> 
00481 typename Field<Data_T>::const_iterator
00482 Field<Data_T>::cbegin(const Box3i &subset) const
00483 {
00484   if (subset.isEmpty())
00485     return cend(subset);
00486   return const_iterator(*this, subset, subset.min);
00487 }
00488 
00489 //----------------------------------------------------------------------------//
00490 
00491 template <class Data_T>
00492 typename Field<Data_T>::const_iterator 
00493 Field<Data_T>::cend() const
00494 { 
00495   return const_iterator(*this, m_dataWindow, 
00496                         V3i(m_dataWindow.min.x, 
00497                             m_dataWindow.min.y,
00498                             m_dataWindow.max.z + 1));
00499 }
00500 
00501 //----------------------------------------------------------------------------//
00502 
00503 template <class Data_T>
00504 typename Field<Data_T>::const_iterator 
00505 Field<Data_T>::cend(const Box3i &subset) const
00506 { 
00507   return const_iterator(*this, subset, V3i(subset.min.x, 
00508                                            subset.min.y,
00509                                            subset.max.z + 1));
00510 }
00511 
00512 //----------------------------------------------------------------------------//
00513 // Field::const_iterator
00514 //----------------------------------------------------------------------------//
00515 
00516 template <class Data_T>
00517 class Field<Data_T>::const_iterator
00518 {
00519 
00520 public:
00521 
00522   // Constructors --------------------------------------------------------------
00523 
00524   const_iterator(const const_iterator &i) 
00525     :  x(i.x), y(i.y), z(i.z), 
00526        m_window(i.m_window), m_field(i.m_field) 
00527   { }
00528 
00529   const_iterator(const Field<Data_T> &field, const Box3i &window,
00530                  const V3i &currentPos)
00531     : x(currentPos.x), y(currentPos.y), z(currentPos.z), 
00532       m_window(window), m_field(field)
00533   { }
00534 
00535   // Operators -----------------------------------------------------------------
00536 
00537   inline const const_iterator& operator ++ ()
00538   {
00539     if (x == m_window.max.x) {
00540       if (y == m_window.max.y) {
00541         x = m_window.min.x;
00542         y = m_window.min.y;
00543         ++z;
00544       } else {
00545         x = m_window.min.x;
00546         ++y;
00547       }
00548     } else {
00549       ++x;
00550     }
00551     return *this;
00552   }
00553   template <class Iter_T>
00554   bool operator == (const Iter_T &rhs) const
00555   {
00556     return x == rhs.x && y == rhs.y && z == rhs.z;
00557   }
00558   template <class Iter_T>
00559   bool operator != (const Iter_T &rhs) const
00560   {
00561     return x != rhs.x || y != rhs.y || z != rhs.z;
00562   }
00563   inline Data_T operator * () const
00564   {
00565     return m_field.value(x, y, z);
00566   }
00567   // Public data members -------------------------------------------------------
00568 
00570   int x, y, z;
00571 
00572 private:
00573 
00574   // Private data members ------------------------------------------------------
00575 
00577   Box3i m_window;
00579   const Field<Data_T> &m_field;
00580 
00581 };
00582 
00583 //----------------------------------------------------------------------------//
00584 // WritableField
00585 //----------------------------------------------------------------------------//
00586 
00593 //----------------------------------------------------------------------------//
00594 
00595 template <class Data_T>
00596 class WritableField 
00597   : public Field<Data_T>
00598 {
00599 public:
00600 
00601   // Typedefs ------------------------------------------------------------------
00602   
00603   typedef boost::intrusive_ptr<WritableField> Ptr;
00604 
00605   // RTTI replacement ----------------------------------------------------------
00606 
00607   typedef WritableField<Data_T> class_type;
00608   DEFINE_FIELD_RTTI_ABSTRACT_CLASS;
00609 
00610   static const char *staticClassName()
00611   {
00612     return "WritableField";
00613   }
00614 
00615   static const char* classType()
00616   {
00617     return WritableField<Data_T>::ms_classType.name();
00618   }
00619   
00620   // Iterators -----------------------------------------------------------------
00621 
00624   class iterator;
00625 
00627   inline iterator begin();
00629   inline iterator begin(const Box3i &subset);
00631   inline iterator end();
00634   inline iterator end(const Box3i &subset);
00635 
00636   // To be implemented by subclasses ------------------------------------------- 
00637 
00646   virtual Data_T& lvalue(int i, int j, int k) = 0;
00647 
00648   // Main methods --------------------------------------------------------------
00649 
00652   virtual void clear(const Data_T &value)
00653   { std::fill(begin(), end(), value); }
00654 
00655 private:
00656 
00657   // Static data members -------------------------------------------------------
00658 
00659   static TemplatedFieldType<WritableField<Data_T> > ms_classType;
00660 
00661   // Typedefs ------------------------------------------------------------------
00662 
00663   typedef Field<Data_T> base;
00664 
00665 };
00666 
00667 //----------------------------------------------------------------------------//
00668 
00669 FIELD3D_CLASSTYPE_TEMPL_INSTANTIATION(WritableField);
00670 
00671 //----------------------------------------------------------------------------//
00672 
00673 template <class Data_T>
00674 inline typename WritableField<Data_T>::iterator 
00675 WritableField<Data_T>::begin()
00676 {
00677   if (FieldRes::dataResolution() == V3i(0))
00678     return end();
00679   return iterator(*this, Field<Data_T>::m_dataWindow, 
00680                   Field<Data_T>::m_dataWindow.min);
00681 }
00682 
00683 //----------------------------------------------------------------------------//
00684 
00685 template <class Data_T>
00686 inline typename WritableField<Data_T>::iterator 
00687 WritableField<Data_T>::begin(const Box3i &subset)
00688 {
00689   if (subset.isEmpty())
00690     return end(subset);
00691   return iterator(*this, subset, subset.min);
00692 }
00693 
00694 //----------------------------------------------------------------------------//
00695 
00696 template <class Data_T>
00697 inline typename WritableField<Data_T>::iterator 
00698 WritableField<Data_T>::end()
00699 { return iterator(*this, Field<Data_T>::m_dataWindow, 
00700                   V3i(Field<Data_T>::m_dataWindow.min.x, 
00701                       Field<Data_T>::m_dataWindow.min.y,
00702                       Field<Data_T>::m_dataWindow.max.z + 1));
00703 }
00704 
00705 //----------------------------------------------------------------------------//
00706 
00707 template <class Data_T>
00708 inline typename WritableField<Data_T>::iterator 
00709 WritableField<Data_T>::end(const Box3i &subset)
00710 { return iterator(*this, subset, 
00711                   V3i(subset.min.x, subset.min.y, subset.max.z + 1));
00712 }
00713 
00714 //----------------------------------------------------------------------------//
00715 // WritableField::iterator
00716 //----------------------------------------------------------------------------//
00717 
00718 template <class Data_T>
00719 class WritableField<Data_T>::iterator
00720 {
00721 public:
00722 
00723   // Constructors --------------------------------------------------------------
00724 
00725   iterator(WritableField<Data_T> &field, const Box3i &window,
00726            const V3i &currentPos)
00727     : x(currentPos.x), y(currentPos.y), z(currentPos.z), 
00728       m_window(window), m_field(field)
00729   { }
00730 
00731   // Operators -----------------------------------------------------------------
00732 
00733   inline const iterator& operator ++ ()
00734   {
00735     if (x == m_window.max.x) {
00736       if (y == m_window.max.y) {
00737         x = m_window.min.x;
00738         y = m_window.min.y;
00739         ++z;
00740       } else {
00741         x = m_window.min.x;
00742         ++y;
00743       }
00744     } else {
00745       ++x;
00746     }
00747     return *this;
00748   }
00749 
00750   template <class Iter_T>
00751   bool operator == (const Iter_T &rhs) const
00752   {
00753     return x == rhs.x && y == rhs.y && z == rhs.z;
00754   }
00755 
00756   template <class Iter_T>
00757   bool operator != (const Iter_T &rhs) const
00758   {
00759     return x != rhs.x || y != rhs.y || z != rhs.z;
00760   }
00761 
00762   inline Data_T& operator * () const
00763   {
00764     return m_field.lvalue(x, y, z);
00765   }
00766 
00767   // Public data members -------------------------------------------------------
00768 
00770   int x, y, z;
00771 
00772 private:
00773 
00774   // Private data members ------------------------------------------------------
00775 
00777   Box3i m_window;
00779   WritableField<Data_T> &m_field;
00780 
00781 };
00782 
00783 //----------------------------------------------------------------------------//
00784 // ResizableField
00785 //----------------------------------------------------------------------------//
00786 
00795 //----------------------------------------------------------------------------//
00796 
00797 template <class Data_T>
00798 class ResizableField
00799   : public WritableField<Data_T>
00800 {
00801 public:
00802 
00803   // Typedefs ------------------------------------------------------------------
00804 
00805   typedef boost::intrusive_ptr<ResizableField> Ptr;
00806 
00807   // RTTI replacement ----------------------------------------------------------
00808 
00809   typedef ResizableField<Data_T> class_type;
00810   DEFINE_FIELD_RTTI_ABSTRACT_CLASS;
00811 
00812   static const char *staticClassName()
00813   {
00814     return "ResizableField";
00815   }
00816   
00817   static const char* classType()
00818   {
00819     return ResizableField<Data_T>::ms_classType.name();
00820   }
00821   
00822   // Main methods --------------------------------------------------------------
00823 
00827   void setSize(const V3i &size);
00831   void setSize(const Box3i &extents);
00835   void setSize(const Box3i &extents, const Box3i &dataWindow);
00839   void setSize(const V3i &size, int padding);
00840 
00842   void copyFrom(typename Field<Data_T>::Ptr other);
00845   template <class Data_T2>
00846   void copyFrom(typename Field<Data_T2>::Ptr other);
00847 
00849   void matchDefinition(FieldRes::Ptr fieldToMatch);
00850 
00851 protected:
00852 
00853   // Static data members -------------------------------------------------------
00854 
00855   static TemplatedFieldType<ResizableField<Data_T> > ms_classType;
00856 
00857   // Typedefs ------------------------------------------------------------------
00858 
00859   typedef WritableField<Data_T> base;
00860 
00861   // To be implemented by subclasses -------------------------------------------
00862 
00866   virtual void sizeChanged()
00867   { base::m_mapping->setExtents(base::m_extents); }
00868 
00869 };
00870 
00871 //----------------------------------------------------------------------------//
00872 
00873 FIELD3D_CLASSTYPE_TEMPL_INSTANTIATION(ResizableField);
00874 
00875 //----------------------------------------------------------------------------//
00876 
00877 template <class Data_T>
00878 void ResizableField<Data_T>::setSize(const V3i &size)
00879 {
00880   Field<Data_T>::m_extents.min = V3i(0);
00881   Field<Data_T>::m_extents.max = size - V3i(1);
00882   Field<Data_T>::m_dataWindow = Field<Data_T>::m_extents;
00883 
00884   // Tell subclasses that the size changed so they can update themselves.
00885   sizeChanged();
00886 }
00887 
00888 //----------------------------------------------------------------------------//
00889 
00890 template <class Data_T>
00891 void ResizableField<Data_T>::setSize(const Box3i &extents)
00892 { 
00893   Field<Data_T>::m_extents = extents;
00894   Field<Data_T>::m_dataWindow = extents;
00895   // Tell subclasses that the size changed so they can update themselves.
00896   sizeChanged();
00897 }
00898 
00899 //----------------------------------------------------------------------------//
00900 
00901 template <class Data_T>
00902 void ResizableField<Data_T>::setSize(const Box3i &extents, 
00903                                      const Box3i &dataWindow)
00904 { 
00905     
00906   Field<Data_T>::m_extents = extents;
00907   Field<Data_T>::m_dataWindow = dataWindow;
00908   // Tell subclasses that the size changed so they can update themselves.
00909   sizeChanged();
00910 }
00911 
00912 //----------------------------------------------------------------------------//
00913 
00914 template <class Data_T>
00915 void ResizableField<Data_T>::setSize(const V3i &size, int padding)
00916 { 
00917   setSize(Box3i(V3i(0), size - V3i(1)),
00918           Box3i(V3i(-padding), 
00919                 size + V3i(padding - 1))); 
00920 }
00921 
00922 //----------------------------------------------------------------------------//
00923 
00924 template <class Data_T>
00925 void ResizableField<Data_T>::copyFrom(typename Field<Data_T>::Ptr other)
00926 {
00927   // Set mapping
00928   FieldRes::setMapping(other->mapping());
00929   // Set size to match
00930   setSize(other->extents(), other->dataWindow());
00931 
00932   // Copy over the data
00933   typename base::iterator i = base::begin();
00934   typename base::iterator end = base::end();
00935   typename Field<Data_T>::const_iterator c = other->cbegin();
00936   for (; i != end; ++i, ++c)
00937     *i = *c;
00938 }
00939 
00940 //----------------------------------------------------------------------------//
00941 
00942 template <class Data_T>
00943 template <class Data_T2>
00944 void ResizableField<Data_T>::copyFrom(typename Field<Data_T2>::Ptr other) 
00945 {
00946   // Set mapping
00947   setMapping(other->mapping());
00948   // Set size to match
00949   setSize(other->extents(), other->dataWindow());
00950   // Copy over the data
00951   typename base::iterator i = base::begin();
00952   typename base::iterator end = base::end();
00953   typename Field<Data_T2>::const_iterator c = other->cbegin();
00954   for (; i != end; ++i, ++c)
00955     *i = *c;
00956 }
00957 
00958 //----------------------------------------------------------------------------//
00959 
00960 template <class Data_T>
00961 void ResizableField<Data_T>::matchDefinition(FieldRes::Ptr fieldToMatch)
00962 {
00963   setSize(fieldToMatch->extents(), fieldToMatch->dataWindow());
00964   FieldRes::setMapping(fieldToMatch->mapping());
00965 }
00966 
00967 //----------------------------------------------------------------------------//
00968 // Field-related utility functions
00969 //----------------------------------------------------------------------------//
00970 
00973 template <class Data_T, class Data_T2>
00974 bool sameDefinition(typename Field<Data_T>::Ptr a, 
00975                     typename Field<Data_T2>::Ptr b)
00976 {
00977   if (a->extents() != b->extents()) {
00978     return false;
00979   } 
00980   if (a->dataWindow() != b->dataWindow()) {
00981     return false;
00982   }
00983   if (!a->mapping()->isIdentical(b->mapping())) {
00984     return false;
00985   }
00986   return true;
00987 }
00988 
00989 //----------------------------------------------------------------------------//
00990 
00993 template <class Data_T>
00994 bool isIdentical(typename Field<Data_T>::Ptr a, typename Field<Data_T>::Ptr b)
00995 {
00996   if (!sameDefinition<Data_T, Data_T>(a, b)) {
00997     return false;
00998   }
00999   // If data window is the same, we can safely assume that the range of
01000   // both fields' iterators are the same.
01001   typename Field<Data_T>::const_iterator is1 = a->cbegin();
01002   typename Field<Data_T>::const_iterator is2 = b->cbegin();
01003   typename Field<Data_T>::const_iterator ie1 = a->cend();
01004   bool same = true;
01005   for (; is1 != ie1; ++is1, ++is2) {
01006     if (*is1 != *is2) {
01007       same = false;
01008       break;
01009     }
01010   }
01011   return same;
01012 }
01013 
01014 //----------------------------------------------------------------------------//
01015 
01018 inline int contToDisc(double contCoord)
01019 {
01020   return static_cast<int>(std::floor(contCoord));
01021 }
01022 
01023 //----------------------------------------------------------------------------//
01024 
01027 inline double discToCont(int discCoord)
01028 {
01029   return static_cast<double>(discCoord) + 0.5;
01030 }
01031 
01032 //----------------------------------------------------------------------------//
01033 
01035 inline V2i contToDisc(const V2d &contCoord)
01036 {
01037   return V2i(contToDisc(contCoord.x), contToDisc(contCoord.y));  
01038 }
01039 
01040 //----------------------------------------------------------------------------//
01041 
01043 inline V2d discToCont(const V2i &discCoord)
01044 {
01045   return V2d(discToCont(discCoord.x), discToCont(discCoord.y));  
01046 }
01047 
01048 //----------------------------------------------------------------------------//
01049 
01051 inline V3i contToDisc(const V3d &contCoord)
01052 {
01053   return V3i(contToDisc(contCoord.x), contToDisc(contCoord.y),
01054              contToDisc(contCoord.z));
01055 }
01056 
01057 //----------------------------------------------------------------------------//
01058 
01060 inline V3d discToCont(const V3i &discCoord)
01061 {
01062   return V3d(discToCont(discCoord.x), discToCont(discCoord.y),
01063              discToCont(discCoord.z));  
01064 }
01065 
01066 //----------------------------------------------------------------------------//
01067 
01069 template <class Iter_T>
01070 void advance(Iter_T &iter, int num) 
01071 {
01072   if (num <= 0) return;
01073   for (int i=0; i<num; ++i, ++iter);
01074 }
01075 
01076 //----------------------------------------------------------------------------//
01077 
01079 template <class Iter_T>
01080 void advance(Iter_T &iter, int num, const Iter_T &end) 
01081 {
01082   if (num <= 0) 
01083     return;
01084   for (int i=0; i<num && iter != end; ++i, ++iter);
01085 }
01086 
01087 //----------------------------------------------------------------------------//
01088 
01089 FIELD3D_NAMESPACE_HEADER_CLOSE
01090 
01091 //----------------------------------------------------------------------------//
01092 
01093 #endif // Include guard
01094