Field3D
Field.h
Go to the documentation of this file.
1 //----------------------------------------------------------------------------//
2 
3 /*
4  * Copyright (c) 2009 Sony Pictures Imageworks Inc
5  *
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  * Redistributions in binary form must reproduce the above copyright
15  * notice, this list of conditions and the following disclaimer in the
16  * documentation and/or other materials provided with the
17  * distribution. Neither the name of Sony Pictures Imageworks nor the
18  * names of its contributors may be used to endorse or promote
19  * products derived from this software without specific prior written
20  * permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
31  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
33  * OF THE POSSIBILITY OF SUCH DAMAGE.
34  */
35 
36 //----------------------------------------------------------------------------//
37 
43 //----------------------------------------------------------------------------//
44 
45 #ifndef _INCLUDED_Field3D_Field_H_
46 #define _INCLUDED_Field3D_Field_H_
47 
48 #include <cmath>
49 #include <vector>
50 #include <map>
51 
52 #include <boost/intrusive_ptr.hpp>
53 #include <boost/thread/mutex.hpp>
54 
55 #include "Traits.h"
56 #include "Exception.h"
57 #include "FieldMapping.h"
58 #include "FieldMetadata.h"
59 #include "Log.h"
60 #include "RefCount.h"
61 #include "Types.h"
62 
63 //----------------------------------------------------------------------------//
64 
65 #include "ns.h"
66 
68 
69 //----------------------------------------------------------------------------//
70 // Exceptions
71 //----------------------------------------------------------------------------//
72 
73 namespace Exc {
74 
75 DECLARE_FIELD3D_GENERIC_EXCEPTION(MemoryException, Exception)
76 DECLARE_FIELD3D_GENERIC_EXCEPTION(ResizeException, Exception)
77 
78 } // namespace Exc
79 
80 //----------------------------------------------------------------------------//
81 // FieldBase
82 //----------------------------------------------------------------------------//
83 
91 class FieldBase : public RefBase
92 {
93 public:
94 
95  // Typedefs ------------------------------------------------------------------
96 
97  typedef boost::intrusive_ptr<FieldBase> Ptr;
99 
100  // Constructors --------------------------------------------------------------
101 
104 
106  FieldBase();
107 
109  FieldBase(const FieldBase &);
110 
112  virtual ~FieldBase();
113 
115 
116  // RTTI replacement ----------------------------------------------------------
117 
118  static const char *staticClassName()
119  {
120  return "FieldBase";
121  }
122 
123  static const char* classType()
124  {
125  return staticClassName();
126  }
127 
128  // To be implemented by subclasses -------------------------------------------
129 
132 
138  virtual std::string className() const = 0;
139 
142  virtual Ptr clone() const = 0;
143 
145 
146  // Access to metadata --------------------------------------------------------
147 
150 
153  { return m_metadata; }
154 
156  const FieldMetadata<FieldBase>& metadata() const
157  { return m_metadata; }
158 
161  virtual void metadataHasChanged(const std::string &/* name */)
162  { /* Empty */ }
163 
165  void copyMetadata(const FieldBase &field)
166  { m_metadata = field.metadata(); }
167 
169 
170  // Public data members -------------------------------------------------------
171 
173  std::string name;
175  std::string attribute;
176 
177  private:
178 
179  // Private data members ------------------------------------------------------
180 
183 
184 };
185 
186 //----------------------------------------------------------------------------//
187 // FieldRes
188 //----------------------------------------------------------------------------//
189 
207 //----------------------------------------------------------------------------//
208 
209 class FieldRes : public FieldBase
210 {
211 public:
212 
213  // Typedefs ------------------------------------------------------------------
214 
215  typedef boost::intrusive_ptr<FieldRes> Ptr;
216  typedef std::vector<Ptr> Vec;
217 
218  // RTTI replacement ----------------------------------------------------------
219 
222 
223  virtual std::string dataTypeString() const
224  { return std::string("FieldRes"); }
225 
226  static const char *staticClassName()
227  {
228  return "FieldRes";
229  }
230 
231  static const char *classType()
232  {
233  return staticClassName();
234  }
235 
236  // Ctor, dtor ----------------------------------------------------------------
237 
239  FieldRes();
240 
243  FieldRes(const FieldRes &src);
244 
245  // Main methods --------------------------------------------------------------
246 
251  inline const Box3i& extents() const
252  { return m_extents; }
255  inline const Box3i& dataWindow() const
256  { return m_dataWindow; }
257 
258  inline V3i const dataResolution() const
259  { return m_dataWindow.max - m_dataWindow.min + V3i(1); }
260 
262  void setMapping(FieldMapping::Ptr mapping);
263 
266  { return m_mapping; }
267 
269  const FieldMapping::Ptr mapping() const
270  { return m_mapping; }
271 
273  bool isInBounds(int i, int j, int k) const;
274 
275  // To be implemented by subclasses -------------------------------------------
276 
281  virtual long long int memSize() const
282  { return sizeof(*this); }
283 
284 protected:
285 
286  // Typedefs ------------------------------------------------------------------
287 
289 
290  // Data members --------------------------------------------------------------
291 
302 
303 private:
304 
305  // Typedefs ------------------------------------------------------------------
306 
308  typedef FieldBase base;
309 
310 };
311 
312 //----------------------------------------------------------------------------//
313 
315  : m_mapping(new default_mapping)
316 {
317  m_extents = Box3i(V3i(0), V3i(-1));
319  m_mapping->setExtents(m_extents);
320 }
321 
322 //----------------------------------------------------------------------------//
323 
324 inline FieldRes::FieldRes(const FieldRes &src)
325  : FieldBase(src)
326 {
327  // Call base class first
328  // FieldBase(src);
329  // Copy self
330  *this = src;
331  m_mapping = src.mapping()->clone();
332 }
333 
334 //----------------------------------------------------------------------------//
335 
337 {
338  if (mapping) {
339  m_mapping = mapping->clone();
340  m_mapping->setExtents(m_extents);
341  } else {
343  "Tried to call FieldRes::setMapping with null pointer");
344  }
345 }
346 
347 //----------------------------------------------------------------------------//
348 
349 inline bool FieldRes::isInBounds(int i, int j, int k) const
350 {
351  // Check bounds
352  if (i < m_dataWindow.min.x || i > m_dataWindow.max.x ||
353  j < m_dataWindow.min.y || j > m_dataWindow.max.y ||
354  k < m_dataWindow.min.z || k > m_dataWindow.max.z) {
355  return false;
356  }
357 
358  return true;
359 }
360 
361 //----------------------------------------------------------------------------//
362 // Field
363 //----------------------------------------------------------------------------//
364 
375 template <class Data_T>
376 class Field : public FieldRes
377 {
378 public:
379 
380  // Typedefs ------------------------------------------------------------------
381 
382  typedef boost::intrusive_ptr<Field> Ptr;
383 
385  typedef Data_T value_type;
386 
390  typedef std::vector<Ptr> Vec;
391 
392  // RTTI replacement ----------------------------------------------------------
393 
396 
397  static const char *staticClassName()
398  {
399  return "Field";
400  }
401 
402  static const char* classType()
403  {
405  }
406 
407  // Constructors --------------------------------------------------------------
408 
410  virtual ~Field()
411  { /* Empty */ }
412 
413  // Iterators -----------------------------------------------------------------
414 
417  class const_iterator;
418 
420  const_iterator cbegin() const;
422  const_iterator cbegin(const Box3i &subset) const;
424  const_iterator cend() const;
427  const_iterator cend(const Box3i &subset) const;
428 
429  // To be implemented by subclasses -------------------------------------------
430 
437  virtual Data_T value(int i, int j, int k) const = 0;
438 
439  // Other member functions ----------------------------------------------------
440 
441  virtual std::string dataTypeString() const
442  { return DataTypeTraits<Data_T>::name(); }
443 
444 
445 private:
446 
447  // Static data members -------------------------------------------------------
448 
450 
451  // Typedefs ------------------------------------------------------------------
452 
454  typedef FieldRes base;
455 
456 };
457 
458 //----------------------------------------------------------------------------//
459 
460 #define FIELD3D_CLASSTYPE_TEMPL_INSTANTIATION(field) \
461  template <typename Data_T> \
462  TemplatedFieldType<field<Data_T> > field<Data_T>::ms_classType = \
463  TemplatedFieldType<field<Data_T> >(); \
464 
466 
467 //----------------------------------------------------------------------------//
468 
469 template <class Data_T>
472 {
473  if (FieldRes::dataResolution() == V3i(0))
474  return cend();
475  return const_iterator(*this, m_dataWindow, m_dataWindow.min);
476 }
477 
478 //----------------------------------------------------------------------------//
479 
480 template <class Data_T>
482 Field<Data_T>::cbegin(const Box3i &subset) const
483 {
484  if (subset.isEmpty())
485  return cend(subset);
486  return const_iterator(*this, subset, subset.min);
487 }
488 
489 //----------------------------------------------------------------------------//
490 
491 template <class Data_T>
494 {
495  return const_iterator(*this, m_dataWindow,
496  V3i(m_dataWindow.min.x,
497  m_dataWindow.min.y,
498  m_dataWindow.max.z + 1));
499 }
500 
501 //----------------------------------------------------------------------------//
502 
503 template <class Data_T>
505 Field<Data_T>::cend(const Box3i &subset) const
506 {
507  return const_iterator(*this, subset, V3i(subset.min.x,
508  subset.min.y,
509  subset.max.z + 1));
510 }
511 
512 //----------------------------------------------------------------------------//
513 // Field::const_iterator
514 //----------------------------------------------------------------------------//
515 
516 template <class Data_T>
517 class Field<Data_T>::const_iterator
518 {
519 
520 public:
521 
522  // Constructors --------------------------------------------------------------
523 
525  : x(i.x), y(i.y), z(i.z),
526  m_window(i.m_window), m_field(i.m_field)
527  { }
528 
529  const_iterator(const Field<Data_T> &field, const Box3i &window,
530  const V3i &currentPos)
531  : x(currentPos.x), y(currentPos.y), z(currentPos.z),
532  m_window(window), m_field(field)
533  { }
534 
535  // Operators -----------------------------------------------------------------
536 
537  inline const const_iterator& operator ++ ()
538  {
539  if (x == m_window.max.x) {
540  if (y == m_window.max.y) {
541  x = m_window.min.x;
542  y = m_window.min.y;
543  ++z;
544  } else {
545  x = m_window.min.x;
546  ++y;
547  }
548  } else {
549  ++x;
550  }
551  return *this;
552  }
553  template <class Iter_T>
554  bool operator == (const Iter_T &rhs) const
555  {
556  return x == rhs.x && y == rhs.y && z == rhs.z;
557  }
558  template <class Iter_T>
559  bool operator != (const Iter_T &rhs) const
560  {
561  return x != rhs.x || y != rhs.y || z != rhs.z;
562  }
563  inline Data_T operator * () const
564  {
565  return m_field.value(x, y, z);
566  }
567  // Public data members -------------------------------------------------------
568 
570  int x, y, z;
571 
572 private:
573 
574  // Private data members ------------------------------------------------------
575 
580 
581 };
582 
583 //----------------------------------------------------------------------------//
584 // WritableField
585 //----------------------------------------------------------------------------//
586 
593 //----------------------------------------------------------------------------//
594 
595 template <class Data_T>
597  : public Field<Data_T>
598 {
599 public:
600 
601  // Typedefs ------------------------------------------------------------------
602 
603  typedef boost::intrusive_ptr<WritableField> Ptr;
604 
605  // RTTI replacement ----------------------------------------------------------
606 
609 
610  static const char *staticClassName()
611  {
612  return "WritableField";
613  }
614 
615  static const char* classType()
616  {
618  }
619 
620  // Iterators -----------------------------------------------------------------
621 
624  class iterator;
625 
627  inline iterator begin();
629  inline iterator begin(const Box3i &subset);
631  inline iterator end();
634  inline iterator end(const Box3i &subset);
635 
636  // To be implemented by subclasses -------------------------------------------
637 
646  virtual Data_T& lvalue(int i, int j, int k) = 0;
647 
648  // Main methods --------------------------------------------------------------
649 
652  virtual void clear(const Data_T &value)
653  { std::fill(begin(), end(), value); }
654 
655 private:
656 
657  // Static data members -------------------------------------------------------
658 
660 
661  // Typedefs ------------------------------------------------------------------
662 
664 
665 };
666 
667 //----------------------------------------------------------------------------//
668 
670 
671 //----------------------------------------------------------------------------//
672 
673 template <class Data_T>
674 inline typename WritableField<Data_T>::iterator
676 {
677  if (FieldRes::dataResolution() == V3i(0))
678  return end();
679  return iterator(*this, Field<Data_T>::m_dataWindow,
681 }
682 
683 //----------------------------------------------------------------------------//
684 
685 template <class Data_T>
686 inline typename WritableField<Data_T>::iterator
688 {
689  if (subset.isEmpty())
690  return end(subset);
691  return iterator(*this, subset, subset.min);
692 }
693 
694 //----------------------------------------------------------------------------//
695 
696 template <class Data_T>
697 inline typename WritableField<Data_T>::iterator
699 { return iterator(*this, Field<Data_T>::m_dataWindow,
702  Field<Data_T>::m_dataWindow.max.z + 1));
703 }
704 
705 //----------------------------------------------------------------------------//
706 
707 template <class Data_T>
708 inline typename WritableField<Data_T>::iterator
710 { return iterator(*this, subset,
711  V3i(subset.min.x, subset.min.y, subset.max.z + 1));
712 }
713 
714 //----------------------------------------------------------------------------//
715 // WritableField::iterator
716 //----------------------------------------------------------------------------//
717 
718 template <class Data_T>
719 class WritableField<Data_T>::iterator
720 {
721 public:
722 
723  // Constructors --------------------------------------------------------------
724 
725  iterator(WritableField<Data_T> &field, const Box3i &window,
726  const V3i &currentPos)
727  : x(currentPos.x), y(currentPos.y), z(currentPos.z),
728  m_window(window), m_field(field)
729  { }
730 
731  // Operators -----------------------------------------------------------------
732 
733  inline const iterator& operator ++ ()
734  {
735  if (x == m_window.max.x) {
736  if (y == m_window.max.y) {
737  x = m_window.min.x;
738  y = m_window.min.y;
739  ++z;
740  } else {
741  x = m_window.min.x;
742  ++y;
743  }
744  } else {
745  ++x;
746  }
747  return *this;
748  }
749 
750  template <class Iter_T>
751  bool operator == (const Iter_T &rhs) const
752  {
753  return x == rhs.x && y == rhs.y && z == rhs.z;
754  }
755 
756  template <class Iter_T>
757  bool operator != (const Iter_T &rhs) const
758  {
759  return x != rhs.x || y != rhs.y || z != rhs.z;
760  }
761 
762  inline Data_T& operator * () const
763  {
764  return m_field.lvalue(x, y, z);
765  }
766 
767  // Public data members -------------------------------------------------------
768 
770  int x, y, z;
771 
772 private:
773 
774  // Private data members ------------------------------------------------------
775 
780 
781 };
782 
783 //----------------------------------------------------------------------------//
784 // ResizableField
785 //----------------------------------------------------------------------------//
786 
795 //----------------------------------------------------------------------------//
796 
797 template <class Data_T>
799  : public WritableField<Data_T>
800 {
801 public:
802 
803  // Typedefs ------------------------------------------------------------------
804 
805  typedef boost::intrusive_ptr<ResizableField> Ptr;
806 
807  // RTTI replacement ----------------------------------------------------------
808 
811 
812  static const char *staticClassName()
813  {
814  return "ResizableField";
815  }
816 
817  static const char* classType()
818  {
820  }
821 
822  // Main methods --------------------------------------------------------------
823 
827  void setSize(const V3i &size);
831  void setSize(const Box3i &extents);
835  void setSize(const Box3i &extents, const Box3i &dataWindow);
839  void setSize(const V3i &size, int padding);
840 
842  void copyFrom(typename Field<Data_T>::Ptr other);
845  template <class Data_T2>
846  void copyFrom(typename Field<Data_T2>::Ptr other);
847 
849  void matchDefinition(FieldRes::Ptr fieldToMatch);
850 
851 protected:
852 
853  // Static data members -------------------------------------------------------
854 
856 
857  // Typedefs ------------------------------------------------------------------
858 
860 
861  // To be implemented by subclasses -------------------------------------------
862 
866  virtual void sizeChanged()
867  { base::m_mapping->setExtents(base::m_extents); }
868 
869 };
870 
871 //----------------------------------------------------------------------------//
872 
874 
875 //----------------------------------------------------------------------------//
876 
877 template <class Data_T>
879 {
880  Field<Data_T>::m_extents.min = V3i(0);
881  Field<Data_T>::m_extents.max = size - V3i(1);
883 
884  // Tell subclasses that the size changed so they can update themselves.
885  sizeChanged();
886 }
887 
888 //----------------------------------------------------------------------------//
889 
890 template <class Data_T>
892 {
893  Field<Data_T>::m_extents = extents;
894  Field<Data_T>::m_dataWindow = extents;
895  // Tell subclasses that the size changed so they can update themselves.
896  sizeChanged();
897 }
898 
899 //----------------------------------------------------------------------------//
900 
901 template <class Data_T>
903  const Box3i &dataWindow)
904 {
905 
906  Field<Data_T>::m_extents = extents;
907  Field<Data_T>::m_dataWindow = dataWindow;
908  // Tell subclasses that the size changed so they can update themselves.
909  sizeChanged();
910 }
911 
912 //----------------------------------------------------------------------------//
913 
914 template <class Data_T>
915 void ResizableField<Data_T>::setSize(const V3i &size, int padding)
916 {
917  setSize(Box3i(V3i(0), size - V3i(1)),
918  Box3i(V3i(-padding),
919  size + V3i(padding - 1)));
920 }
921 
922 //----------------------------------------------------------------------------//
923 
924 template <class Data_T>
926 {
927  // Set mapping
928  FieldRes::setMapping(other->mapping());
929  // Set size to match
930  setSize(other->extents(), other->dataWindow());
931 
932  // Copy over the data
933  typename base::iterator i = base::begin();
934  typename base::iterator end = base::end();
935  typename Field<Data_T>::const_iterator c = other->cbegin();
936  for (; i != end; ++i, ++c)
937  *i = *c;
938 }
939 
940 //----------------------------------------------------------------------------//
941 
942 template <class Data_T>
943 template <class Data_T2>
945 {
946  // Set mapping
947  setMapping(other->mapping());
948  // Set size to match
949  setSize(other->extents(), other->dataWindow());
950  // Copy over the data
951  typename base::iterator i = base::begin();
952  typename base::iterator end = base::end();
953  typename Field<Data_T2>::const_iterator c = other->cbegin();
954  for (; i != end; ++i, ++c)
955  *i = *c;
956 }
957 
958 //----------------------------------------------------------------------------//
959 
960 template <class Data_T>
962 {
963  setSize(fieldToMatch->extents(), fieldToMatch->dataWindow());
964  FieldRes::setMapping(fieldToMatch->mapping());
965 }
966 
967 //----------------------------------------------------------------------------//
968 // Field-related utility functions
969 //----------------------------------------------------------------------------//
970 
973 template <class Data_T, class Data_T2>
975  typename Field<Data_T2>::Ptr b)
976 {
977  if (a->extents() != b->extents()) {
978  return false;
979  }
980  if (a->dataWindow() != b->dataWindow()) {
981  return false;
982  }
983  if (!a->mapping()->isIdentical(b->mapping())) {
984  return false;
985  }
986  return true;
987 }
988 
989 //----------------------------------------------------------------------------//
990 
993 template <class Data_T>
995 {
996  if (!sameDefinition<Data_T, Data_T>(a, b)) {
997  return false;
998  }
999  // If data window is the same, we can safely assume that the range of
1000  // both fields' iterators are the same.
1001  typename Field<Data_T>::const_iterator is1 = a->cbegin();
1002  typename Field<Data_T>::const_iterator is2 = b->cbegin();
1003  typename Field<Data_T>::const_iterator ie1 = a->cend();
1004  bool same = true;
1005  for (; is1 != ie1; ++is1, ++is2) {
1006  if (*is1 != *is2) {
1007  same = false;
1008  break;
1009  }
1010  }
1011  return same;
1012 }
1013 
1014 //----------------------------------------------------------------------------//
1015 
1018 inline int contToDisc(double contCoord)
1019 {
1020  return static_cast<int>(std::floor(contCoord));
1021 }
1022 
1023 //----------------------------------------------------------------------------//
1024 
1027 inline double discToCont(int discCoord)
1028 {
1029  return static_cast<double>(discCoord) + 0.5;
1030 }
1031 
1032 //----------------------------------------------------------------------------//
1033 
1035 inline V2i contToDisc(const V2d &contCoord)
1036 {
1037  return V2i(contToDisc(contCoord.x), contToDisc(contCoord.y));
1038 }
1039 
1040 //----------------------------------------------------------------------------//
1041 
1043 inline V2d discToCont(const V2i &discCoord)
1044 {
1045  return V2d(discToCont(discCoord.x), discToCont(discCoord.y));
1046 }
1047 
1048 //----------------------------------------------------------------------------//
1049 
1051 inline V3i contToDisc(const V3d &contCoord)
1052 {
1053  return V3i(contToDisc(contCoord.x), contToDisc(contCoord.y),
1054  contToDisc(contCoord.z));
1055 }
1056 
1057 //----------------------------------------------------------------------------//
1058 
1060 inline V3d discToCont(const V3i &discCoord)
1061 {
1062  return V3d(discToCont(discCoord.x), discToCont(discCoord.y),
1063  discToCont(discCoord.z));
1064 }
1065 
1066 //----------------------------------------------------------------------------//
1067 
1069 template <class Iter_T>
1070 void advance(Iter_T &iter, int num)
1071 {
1072  if (num <= 0) return;
1073  for (int i=0; i<num; ++i, ++iter);
1074 }
1075 
1076 //----------------------------------------------------------------------------//
1077 
1079 template <class Iter_T>
1080 void advance(Iter_T &iter, int num, const Iter_T &end)
1081 {
1082  if (num <= 0)
1083  return;
1084  for (int i=0; i<num && iter != end; ++i, ++iter);
1085 }
1086 
1087 //----------------------------------------------------------------------------//
1088 
1090 
1091 //----------------------------------------------------------------------------//
1092 
1093 #endif // Include guard
1094