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 // Field RTTI Replacement
00071 //----------------------------------------------------------------------------//
00072 
00073 #define DEFINE_CHECK_RTTI_CALL \
00074   virtual bool checkRTTI(const std::string &typenameStr) \
00075   { return matchRTTI(typenameStr); } \
00076 
00077 #define DEFINE_MATCH_RTTI_CALL \
00078   bool matchRTTI(const std::string &typenameStr) \
00079   { \
00080     if (typenameStr == typeid(class_type).name()) { \
00081       return true; \
00082     } \
00083     return base::matchRTTI(typenameStr); \
00084   }
00085 
00086 #define DEFINE_FIELD_RTTI_CONCRETE_CLASS \
00087   DEFINE_CHECK_RTTI_CALL \
00088   DEFINE_MATCH_RTTI_CALL
00089 
00090 #define DEFINE_FIELD_RTTI_ABSTRACT_CLASS \
00091   DEFINE_MATCH_RTTI_CALL
00092 
00093 //----------------------------------------------------------------------------//
00094 // Exceptions
00095 //----------------------------------------------------------------------------//
00096 
00097 namespace Exc {
00098 
00099 DECLARE_FIELD3D_GENERIC_EXCEPTION(MemoryException, Exception)
00100 DECLARE_FIELD3D_GENERIC_EXCEPTION(ResizeException, Exception)
00101 
00102 } // namespace Exc
00103 
00104 //----------------------------------------------------------------------------//
00105 // FieldTraits
00106 //----------------------------------------------------------------------------//
00107 
00113 template <class Data_T>
00114 class FieldTraits
00115 {
00116  public:
00118   static int dataDims();
00119 };
00120 
00121 //----------------------------------------------------------------------------//
00122 // FieldBase
00123 //----------------------------------------------------------------------------//
00124 
00132 class FieldBase : public RefBase
00133 {
00134 public:
00135 
00136   // Typedefs ------------------------------------------------------------------
00137 
00138   typedef boost::intrusive_ptr<FieldBase> Ptr;
00139   typedef FieldBase class_type;
00140 
00141   // Constructors --------------------------------------------------------------
00142 
00145 
00147   FieldBase();
00148 
00150   FieldBase(const FieldBase &);
00151 
00153   virtual ~FieldBase();
00154 
00156 
00157   // To be implemented by subclasses -------------------------------------------
00158 
00161 
00164   virtual std::string className() const = 0;
00165 
00168   virtual Ptr clone() const = 0;
00169 
00171   
00172   // RTTI replacement ----------------------------------------------------------
00173 
00182 
00183 
00184 
00187   virtual bool checkRTTI(const std::string &typenameStr) = 0;
00188   
00191   bool matchRTTI(const std::string &typenameStr)
00192   { return typenameStr == typeid(*this).name(); }
00193 
00195 
00196   // Access to metadata --------------------------------------------------------
00197 
00200 
00202   FieldMetadata<FieldBase>& metadata()
00203   { return m_metadata; }
00204 
00206   const FieldMetadata<FieldBase>& metadata() const
00207   { return m_metadata; }
00208 
00211   virtual void metadataHasChanged(const std::string &/* name */) 
00212   { /* Empty */ }
00213 
00215   void copyMetadata(const FieldBase &field)
00216   { m_metadata = field.metadata(); }
00217 
00219 
00220   // Public data members -------------------------------------------------------
00221 
00223   std::string name;
00225   std::string attribute;
00226 
00227  private:
00228 
00229   // Private data members ------------------------------------------------------
00230 
00232   FieldMetadata<FieldBase> m_metadata;
00233 
00234 };
00235 
00236 //----------------------------------------------------------------------------//
00237 // FieldRes
00238 //----------------------------------------------------------------------------//
00239 
00257 class FieldRes : public FieldBase
00258 {
00259 public:
00260 
00261   // Typedefs ------------------------------------------------------------------
00262 
00263   typedef boost::intrusive_ptr<FieldRes> Ptr;
00264   typedef std::vector<Ptr> Vec;
00265 
00266   virtual std::string dataTypeString() const = 0;
00267 
00268   // RTTI replacement ----------------------------------------------------------
00269 
00270   typedef FieldRes class_type;
00271   DEFINE_FIELD_RTTI_ABSTRACT_CLASS;
00272   
00273   // Ctor, dtor ----------------------------------------------------------------
00274 
00276   FieldRes();
00277 
00280   FieldRes(const FieldRes &src);
00281 
00282   // Main methods --------------------------------------------------------------
00283 
00288   inline const Box3i& extents() const
00289   { return m_extents; }
00292   inline const Box3i& dataWindow() const
00293   { return m_dataWindow; }
00294 
00295   inline V3i const dataResolution() const
00296   { return m_dataWindow.max - m_dataWindow.min + V3i(1); }
00297 
00299   void setMapping(FieldMapping::Ptr mapping);
00300 
00302   FieldMapping::Ptr mapping()
00303   { return m_mapping; }
00304 
00306   const FieldMapping::Ptr mapping() const
00307   { return m_mapping; }
00308 
00310   bool isInBounds(int i, int j, int k);
00311 
00312   // To be implemented by subclasses -------------------------------------------
00313 
00318   virtual long long int memSize() const
00319   { return sizeof(*this); }
00320 
00321 protected:
00322 
00323   // Typedefs ------------------------------------------------------------------
00324 
00325   typedef MatrixFieldMapping default_mapping;
00326 
00327   // Data members --------------------------------------------------------------
00328 
00333   Box3i m_extents;
00336   Box3i m_dataWindow;
00338   FieldMapping::Ptr m_mapping;
00339   
00340 private:
00341 
00342   // Typedefs ------------------------------------------------------------------
00343 
00345   typedef FieldBase base;
00346 
00347 };
00348 
00349 //----------------------------------------------------------------------------//
00350 
00351 inline FieldRes::FieldRes()
00352   : m_mapping(new default_mapping)
00353 { 
00354   m_extents = Box3i(V3i(0), V3i(-1));
00355   m_dataWindow = m_extents;
00356   m_mapping->setExtents(m_extents); 
00357 }
00358 
00359 //----------------------------------------------------------------------------//
00360 
00361 inline FieldRes::FieldRes(const FieldRes &src) 
00362   : FieldBase(src)
00363 {
00364   // Call base class first
00365   // FieldBase(src);
00366   // Copy self
00367   *this = src;
00368   m_mapping = src.mapping()->clone();
00369 }
00370 
00371 //----------------------------------------------------------------------------//
00372 
00373 inline void FieldRes::setMapping(FieldMapping::Ptr mapping)
00374 { 
00375   if (mapping) {
00376     m_mapping = mapping->clone(); 
00377     m_mapping->setExtents(m_extents); 
00378   } else {
00379     Msg::print(Msg::SevWarning, 
00380                "Tried to call FieldRes::setMapping with null pointer");
00381   }
00382 }
00383 
00384 //----------------------------------------------------------------------------//
00385 
00386 inline bool FieldRes::isInBounds(int i, int j, int k) 
00387 {
00388   // Check bounds
00389   if (i < m_dataWindow.min.x || i > m_dataWindow.max.x ||
00390       j < m_dataWindow.min.y || j > m_dataWindow.max.y ||
00391       k < m_dataWindow.min.z || k > m_dataWindow.max.z) {
00392     return false;
00393   }
00394 
00395   return true;
00396 }
00397 
00398 //----------------------------------------------------------------------------//
00399 // field_dynamic_cast
00400 //----------------------------------------------------------------------------//
00401 
00405 template <class Field_T>
00406 typename Field_T::Ptr
00407 field_dynamic_cast(FieldBase::Ptr field)
00408 {
00409   if (!field) 
00410     return NULL;
00411   std::string tgtTypeString = typeid(Field_T).name();
00412   if (field->checkRTTI(tgtTypeString)) {
00413     return static_cast<Field_T*>(field.get());
00414   } else {
00415     return NULL;
00416   }
00417 }
00418 
00419 //----------------------------------------------------------------------------//
00420 // Field
00421 //----------------------------------------------------------------------------//
00422 
00433 template <class Data_T>
00434 class Field : public FieldRes
00435 {
00436  public:
00437 
00438   // Typedefs ------------------------------------------------------------------
00439   
00440   typedef boost::intrusive_ptr<Field> Ptr;
00441 
00443   typedef Data_T value_type;
00444 
00448   typedef std::vector<Ptr> Vec;
00449 
00450   // RTTI replacement ----------------------------------------------------------
00451 
00452   typedef Field<Data_T> class_type;
00453   DEFINE_FIELD_RTTI_ABSTRACT_CLASS;
00454   
00455   // Constructors --------------------------------------------------------------
00456 
00458   virtual ~Field()
00459   { /* Empty */ }
00460 
00461   // Iterators -----------------------------------------------------------------
00462 
00465   class const_iterator;
00466 
00468   const_iterator cbegin() const;
00470   const_iterator cbegin(const Box3i &subset) const;
00472   const_iterator cend() const;
00475   const_iterator cend(const Box3i &subset) const;
00476 
00477   // To be implemented by subclasses -------------------------------------------
00478 
00485   virtual Data_T value(int i, int j, int k) const = 0;
00486 
00487   // Other member functions ----------------------------------------------------
00488 
00489   virtual std::string dataTypeString() const 
00490   { return DataTypeTraits<Data_T>::name(); }
00491 
00492 private:
00493 
00494   // Typedefs ------------------------------------------------------------------
00495 
00497   typedef FieldRes base;
00498 
00499 };
00500 
00501 //----------------------------------------------------------------------------//
00502 
00503 template <class Data_T> 
00504 typename Field<Data_T>::const_iterator 
00505 Field<Data_T>::cbegin() const
00506 {
00507   if (FieldRes::dataResolution() == V3i(0))
00508     return cend();
00509   return const_iterator(*this, m_dataWindow, m_dataWindow.min);
00510 }
00511 
00512 //----------------------------------------------------------------------------//
00513 
00514 template <class Data_T> 
00515 typename Field<Data_T>::const_iterator
00516 Field<Data_T>::cbegin(const Box3i &subset) const
00517 {
00518   if (subset.isEmpty())
00519     return cend(subset);
00520   return const_iterator(*this, subset, subset.min);
00521 }
00522 
00523 //----------------------------------------------------------------------------//
00524 
00525 template <class Data_T>
00526 typename Field<Data_T>::const_iterator 
00527 Field<Data_T>::cend() const
00528 { 
00529   return const_iterator(*this, m_dataWindow, 
00530                         V3i(m_dataWindow.min.x, 
00531                             m_dataWindow.min.y,
00532                             m_dataWindow.max.z + 1));
00533 }
00534 
00535 //----------------------------------------------------------------------------//
00536 
00537 template <class Data_T>
00538 typename Field<Data_T>::const_iterator 
00539 Field<Data_T>::cend(const Box3i &subset) const
00540 { 
00541   return const_iterator(*this, subset, V3i(subset.min.x, 
00542                                            subset.min.y,
00543                                            subset.max.z + 1));
00544 }
00545 
00546 //----------------------------------------------------------------------------//
00547 // Field::const_iterator
00548 //----------------------------------------------------------------------------//
00549 
00550 template <class Data_T>
00551 class Field<Data_T>::const_iterator
00552 {
00553 
00554 public:
00555 
00556   // Constructors --------------------------------------------------------------
00557 
00558   const_iterator(const const_iterator &i) 
00559     :  x(i.x), y(i.y), z(i.z), 
00560        m_window(i.m_window), m_field(i.m_field) 
00561   { }
00562 
00563   const_iterator(const Field<Data_T> &field, const Box3i &window,
00564                  const V3i &currentPos)
00565     : x(currentPos.x), y(currentPos.y), z(currentPos.z), 
00566       m_window(window), m_field(field)
00567   { }
00568 
00569   // Operators -----------------------------------------------------------------
00570 
00571   inline const const_iterator& operator ++ ()
00572   {
00573     if (x == m_window.max.x) {
00574       if (y == m_window.max.y) {
00575         x = m_window.min.x;
00576         y = m_window.min.y;
00577         ++z;
00578       } else {
00579         x = m_window.min.x;
00580         ++y;
00581       }
00582     } else {
00583       ++x;
00584     }
00585     return *this;
00586   }
00587   template <class Iter_T>
00588   bool operator == (const Iter_T &rhs) const
00589   {
00590     return x == rhs.x && y == rhs.y && z == rhs.z;
00591   }
00592   template <class Iter_T>
00593   bool operator != (const Iter_T &rhs) const
00594   {
00595     return x != rhs.x || y != rhs.y || z != rhs.z;
00596   }
00597   inline Data_T operator * () const
00598   {
00599     return m_field.value(x, y, z);
00600   }
00601   // Public data members -------------------------------------------------------
00602 
00604   int x, y, z;
00605 
00606 private:
00607 
00608   // Private data members ------------------------------------------------------
00609 
00611   Box3i m_window;
00613   const Field<Data_T> &m_field;
00614 
00615 };
00616 
00617 //----------------------------------------------------------------------------//
00618 // WritableField
00619 //----------------------------------------------------------------------------//
00620 
00627 //----------------------------------------------------------------------------//
00628 
00629 template <class Data_T>
00630 class WritableField 
00631   : public Field<Data_T>
00632 {
00633 public:
00634 
00635   // Typedefs ------------------------------------------------------------------
00636   
00637   typedef boost::intrusive_ptr<WritableField> Ptr;
00638 
00639   // RTTI replacement ----------------------------------------------------------
00640 
00641   typedef WritableField<Data_T> class_type;
00642   DEFINE_FIELD_RTTI_ABSTRACT_CLASS;
00643   
00644   // Iterators -----------------------------------------------------------------
00645 
00648   class iterator;
00649 
00651   inline iterator begin();
00653   inline iterator begin(const Box3i &subset);
00655   inline iterator end();
00658   inline iterator end(const Box3i &subset);
00659 
00660   // To be implemented by subclasses ------------------------------------------- 
00661 
00670   virtual Data_T& lvalue(int i, int j, int k) = 0;
00671 
00672   // Main methods --------------------------------------------------------------
00673 
00676   virtual void clear(const Data_T &value)
00677   { std::fill(begin(), end(), value); }
00678 
00679 private:
00680 
00681   // Typedefs ------------------------------------------------------------------
00682 
00683   typedef Field<Data_T> base;
00684 
00685 };
00686 
00687 //----------------------------------------------------------------------------//
00688 
00689 template <class Data_T>
00690 inline typename WritableField<Data_T>::iterator 
00691 WritableField<Data_T>::begin()
00692 {
00693   if (FieldRes::dataResolution() == V3i(0))
00694     return end();
00695   return iterator(*this, Field<Data_T>::m_dataWindow, 
00696                   Field<Data_T>::m_dataWindow.min);
00697 }
00698 
00699 //----------------------------------------------------------------------------//
00700 
00701 template <class Data_T>
00702 inline typename WritableField<Data_T>::iterator 
00703 WritableField<Data_T>::begin(const Box3i &subset)
00704 {
00705   if (subset.isEmpty())
00706     return end(subset);
00707   return iterator(*this, subset, subset.min);
00708 }
00709 
00710 //----------------------------------------------------------------------------//
00711 
00712 template <class Data_T>
00713 inline typename WritableField<Data_T>::iterator 
00714 WritableField<Data_T>::end()
00715 { return iterator(*this, Field<Data_T>::m_dataWindow, 
00716                   V3i(Field<Data_T>::m_dataWindow.min.x, 
00717                       Field<Data_T>::m_dataWindow.min.y,
00718                       Field<Data_T>::m_dataWindow.max.z + 1));
00719 }
00720 
00721 //----------------------------------------------------------------------------//
00722 
00723 template <class Data_T>
00724 inline typename WritableField<Data_T>::iterator 
00725 WritableField<Data_T>::end(const Box3i &subset)
00726 { return iterator(*this, subset, 
00727                   V3i(subset.min.x, subset.min.y, subset.max.z + 1));
00728 }
00729 
00730 //----------------------------------------------------------------------------//
00731 // WritableField::iterator
00732 //----------------------------------------------------------------------------//
00733 
00734 template <class Data_T>
00735 class WritableField<Data_T>::iterator
00736 {
00737 
00738 public:
00739 
00740   // Constructors --------------------------------------------------------------
00741 
00742   iterator(WritableField<Data_T> &field, const Box3i &window,
00743            const V3i &currentPos)
00744     : x(currentPos.x), y(currentPos.y), z(currentPos.z), 
00745       m_window(window), m_field(field)
00746   { }
00747 
00748   // Operators -----------------------------------------------------------------
00749 
00750   inline const iterator& operator ++ ()
00751   {
00752     if (x == m_window.max.x) {
00753       if (y == m_window.max.y) {
00754         x = m_window.min.x;
00755         y = m_window.min.y;
00756         ++z;
00757       } else {
00758         x = m_window.min.x;
00759         ++y;
00760       }
00761     } else {
00762       ++x;
00763     }
00764     return *this;
00765   }
00766 
00767   template <class Iter_T>
00768   bool operator == (const Iter_T &rhs) const
00769   {
00770     return x == rhs.x && y == rhs.y && z == rhs.z;
00771   }
00772 
00773   template <class Iter_T>
00774   bool operator != (const Iter_T &rhs) const
00775   {
00776     return x != rhs.x || y != rhs.y || z != rhs.z;
00777   }
00778 
00779   inline Data_T& operator * () const
00780   {
00781     return m_field.lvalue(x, y, z);
00782   }
00783 
00784   // Public data members -------------------------------------------------------
00785 
00787   int x, y, z;
00788 
00789 private:
00790 
00791   // Private data members ------------------------------------------------------
00792 
00794   Box3i m_window;
00796   WritableField<Data_T> &m_field;
00797 
00798 };
00799 
00800 //----------------------------------------------------------------------------//
00801 // ResizableField
00802 //----------------------------------------------------------------------------//
00803 
00812 //----------------------------------------------------------------------------//
00813 
00814 template <class Data_T>
00815 class ResizableField
00816   : public WritableField<Data_T>
00817 {
00818 public:
00819 
00820   // Typedefs ------------------------------------------------------------------
00821 
00822   typedef boost::intrusive_ptr<ResizableField> Ptr;
00823 
00824   // RTTI replacement ----------------------------------------------------------
00825 
00826   typedef ResizableField<Data_T> class_type;
00827   DEFINE_FIELD_RTTI_ABSTRACT_CLASS;
00828   
00829   // Main methods --------------------------------------------------------------
00830 
00834   void setSize(const V3i &size);
00838   void setSize(const Box3i &extents);
00842   void setSize(const Box3i &extents, const Box3i &dataWindow);
00846   void setSize(const V3i &size, int padding);
00847 
00849   void copyFrom(typename Field<Data_T>::Ptr other);
00852   template <class Data_T2>
00853   void copyFrom(typename Field<Data_T2>::Ptr other);
00854 
00856   void matchDefinition(FieldRes::Ptr fieldToMatch);
00857 
00858 protected:
00859 
00860   // Typedefs ------------------------------------------------------------------
00861 
00862   typedef WritableField<Data_T> base;
00863 
00864   // To be implemented by subclasses -------------------------------------------
00865 
00869   virtual void sizeChanged()
00870   { base::m_mapping->setExtents(base::m_extents); }
00871 
00872 };
00873 
00874 //----------------------------------------------------------------------------//
00875 
00876 template <class Data_T>
00877 void ResizableField<Data_T>::setSize(const V3i &size)
00878 {
00879   Field<Data_T>::m_extents.min = V3i(0);
00880   Field<Data_T>::m_extents.max = size - V3i(1);
00881   Field<Data_T>::m_dataWindow = Field<Data_T>::m_extents;
00882 
00883   // Tell subclasses that the size changed so they can update themselves.
00884   sizeChanged();
00885 }
00886 
00887 //----------------------------------------------------------------------------//
00888 
00889 template <class Data_T>
00890 void ResizableField<Data_T>::setSize(const Box3i &extents)
00891 { 
00892   Field<Data_T>::m_extents = extents;
00893   Field<Data_T>::m_dataWindow = extents;
00894   // Tell subclasses that the size changed so they can update themselves.
00895   sizeChanged();
00896 }
00897 
00898 //----------------------------------------------------------------------------//
00899 
00900 template <class Data_T>
00901 void ResizableField<Data_T>::setSize(const Box3i &extents, 
00902                                      const Box3i &dataWindow)
00903 { 
00904     
00905   Field<Data_T>::m_extents = extents;
00906   Field<Data_T>::m_dataWindow = dataWindow;
00907   // Tell subclasses that the size changed so they can update themselves.
00908   sizeChanged();
00909 }
00910 
00911 //----------------------------------------------------------------------------//
00912 
00913 template <class Data_T>
00914 void ResizableField<Data_T>::setSize(const V3i &size, int padding)
00915 { 
00916   setSize(Box3i(V3i(0), size - V3i(1)),
00917           Box3i(V3i(-padding), 
00918                 size + V3i(padding - 1))); 
00919 }
00920 
00921 //----------------------------------------------------------------------------//
00922 
00923 template <class Data_T>
00924 void ResizableField<Data_T>::copyFrom(typename Field<Data_T>::Ptr other)
00925 {
00926   // Set mapping
00927   setMapping(other->mapping());
00928   // Set size to match
00929   setSize(other->extents(), other->dataWindow());
00930 
00931   // Copy over the data
00932   typename base::iterator i = base::begin();
00933   typename base::iterator end = base::end();
00934   typename Field<Data_T>::const_iterator c = other->cbegin();
00935   for (; i != end; ++i, ++c)
00936     *i = *c;
00937 }
00938 
00939 //----------------------------------------------------------------------------//
00940 
00941 template <class Data_T>
00942 template <class Data_T2>
00943 void ResizableField<Data_T>::copyFrom(typename Field<Data_T2>::Ptr other) 
00944 {
00945   // Set mapping
00946   setMapping(other->mapping());
00947   // Set size to match
00948   setSize(other->extents(), other->dataWindow());
00949   // Copy over the data
00950   typename base::iterator i = base::begin();
00951   typename base::iterator end = base::end();
00952   typename Field<Data_T2>::const_iterator c = other->cbegin();
00953   for (; i != end; ++i, ++c)
00954     *i = *c;
00955 }
00956 
00957 //----------------------------------------------------------------------------//
00958 
00959 template <class Data_T>
00960 void ResizableField<Data_T>::matchDefinition(FieldRes::Ptr fieldToMatch)
00961 {
00962   setSize(fieldToMatch->extents(), fieldToMatch->dataWindow());
00963   FieldRes::setMapping(fieldToMatch->mapping());
00964 }
00965 
00966 //----------------------------------------------------------------------------//
00967 // Field-related utility functions
00968 //----------------------------------------------------------------------------//
00969 
00972 template <class Data_T, class Data_T2>
00973 bool sameDefinition(typename Field<Data_T>::Ptr a, 
00974                     typename Field<Data_T2>::Ptr b)
00975 {
00976   if (a->extents() != b->extents()) {
00977     return false;
00978   } 
00979   if (a->dataWindow() != b->dataWindow()) {
00980     return false;
00981   }
00982   if (!a->mapping()->isIdentical(b->mapping())) {
00983     return false;
00984   }
00985   return true;
00986 }
00987 
00988 //----------------------------------------------------------------------------//
00989 
00992 template <class Data_T>
00993 bool isIdentical(typename Field<Data_T>::Ptr a, typename Field<Data_T>::Ptr b)
00994 {
00995   if (!sameDefinition<Data_T, Data_T>(a, b)) {
00996     return false;
00997   }
00998   // If data window is the same, we can safely assume that the range of
00999   // both fields' iterators are the same.
01000   typename Field<Data_T>::const_iterator is1 = a->cbegin();
01001   typename Field<Data_T>::const_iterator is2 = b->cbegin();
01002   typename Field<Data_T>::const_iterator ie1 = a->cend();
01003   bool same = true;
01004   for (; is1 != ie1; ++is1, ++is2) {
01005     if (*is1 != *is2) {
01006       same = false;
01007       break;
01008     }
01009   }
01010   return same;
01011 }
01012 
01013 //----------------------------------------------------------------------------//
01014 
01017 inline int contToDisc(double contCoord)
01018 {
01019   return static_cast<int>(std::floor(contCoord));
01020 }
01021 
01022 //----------------------------------------------------------------------------//
01023 
01026 inline double discToCont(int discCoord)
01027 {
01028   return static_cast<double>(discCoord) + 0.5;
01029 }
01030 
01031 //----------------------------------------------------------------------------//
01032 
01034 inline V2i contToDisc(const V2d &contCoord)
01035 {
01036   return V2i(contToDisc(contCoord.x), contToDisc(contCoord.y));  
01037 }
01038 
01039 //----------------------------------------------------------------------------//
01040 
01042 inline V2d discToCont(const V2i &discCoord)
01043 {
01044   return V2d(discToCont(discCoord.x), discToCont(discCoord.y));  
01045 }
01046 
01047 //----------------------------------------------------------------------------//
01048 
01050 inline V3i contToDisc(const V3d &contCoord)
01051 {
01052   return V3i(contToDisc(contCoord.x), contToDisc(contCoord.y),
01053              contToDisc(contCoord.z));
01054 }
01055 
01056 //----------------------------------------------------------------------------//
01057 
01059 inline V3d discToCont(const V3i &discCoord)
01060 {
01061   return V3d(discToCont(discCoord.x), discToCont(discCoord.y),
01062              discToCont(discCoord.z));  
01063 }
01064 
01065 //----------------------------------------------------------------------------//
01066 
01068 template <class Iter_T>
01069 void advance(Iter_T &iter, int num) 
01070 {
01071   if (num <= 0) return;
01072   for (int i=0; i<num; ++i, ++iter);
01073 }
01074 
01075 //----------------------------------------------------------------------------//
01076 
01078 template <class Iter_T>
01079 void advance(Iter_T &iter, int num, const Iter_T &end) 
01080 {
01081   if (num <= 0) 
01082     return;
01083   for (int i=0; i<num && iter != end; ++i, ++iter);
01084 }
01085 
01086 //----------------------------------------------------------------------------//
01087 
01088 FIELD3D_NAMESPACE_HEADER_CLOSE
01089 
01090 //----------------------------------------------------------------------------//
01091 
01092 #endif // Include guard
01093