Field3D
SparseField.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 
42 //----------------------------------------------------------------------------//
43 
44 #ifndef _INCLUDED_Field3D_SparseField_H_
45 #define _INCLUDED_Field3D_SparseField_H_
46 
47 //----------------------------------------------------------------------------//
48 
49 #include <vector>
50 
51 #include <boost/thread/mutex.hpp>
52 #include <boost/lexical_cast.hpp>
53 
54 #include "Field.h"
55 #include "SparseFile.h"
56 
57 #define BLOCK_ORDER 4 // 2^BLOCK_ORDER is the block size along each axis
58 
59 //----------------------------------------------------------------------------//
60 
61 #include "ns.h"
62 
64 
65 //----------------------------------------------------------------------------//
66 // Forward declarations
67 //----------------------------------------------------------------------------//
68 
69 template <class Field_T>
71 template <class Field_T>
73 
74 //----------------------------------------------------------------------------//
75 // LinearSparseFieldInterp
76 //----------------------------------------------------------------------------//
77 
78 /* \class LinearSparseFieldInterp
79  \ingroup field
80  \brief Linear interpolator optimized for fields with a fastValue function
81 */
82 
83 //----------------------------------------------------------------------------//
84 
85 template <typename Data_T>
87 {
88 public:
89 
90  // Typedefs ------------------------------------------------------------------
91 
92  typedef Data_T value_type;
93  typedef boost::intrusive_ptr<LinearSparseFieldInterp> Ptr;
94 
95  // RTTI replacement ----------------------------------------------------------
96 
99 
100  static const char *staticClassName()
101  {
102  return "LinearSparseFieldInterp";
103  }
104 
105  static const char* staticClassType()
106  {
107  return ms_classType.name();
108  }
109 
110  // Main methods --------------------------------------------------------------
111 
112  value_type sample(const SparseField<Data_T> &field, const V3d &vsP) const
113  {
114  // Pixel centers are at .5 coordinates
115  // NOTE: Don't use contToDisc for this, we're looking for sample
116  // point locations, not coordinate shifts.
117  FIELD3D_VEC3_T<double> p(vsP - FIELD3D_VEC3_T<double>(0.5));
118 
119  // Lower left corner
120  V3i c1(static_cast<int>(floor(p.x)),
121  static_cast<int>(floor(p.y)),
122  static_cast<int>(floor(p.z)));
123  // Upper right corner
124  V3i c2(c1 + V3i(1));
125  // C1 fractions
126  FIELD3D_VEC3_T<double> f1(static_cast<FIELD3D_VEC3_T<double> >(c2) - p);
127  // C2 fraction
128  FIELD3D_VEC3_T<double> f2(static_cast<FIELD3D_VEC3_T<double> >(1.0) - f1);
129 
130  const Box3i &dataWindow = field.dataWindow();
131 
132  // Clamp the coordinates
133  c1.x = std::min(dataWindow.max.x, std::max(dataWindow.min.x, c1.x));
134  c1.y = std::min(dataWindow.max.y, std::max(dataWindow.min.y, c1.y));
135  c1.z = std::min(dataWindow.max.z, std::max(dataWindow.min.z, c1.z));
136  c2.x = std::min(dataWindow.max.x, std::max(dataWindow.min.x, c2.x));
137  c2.y = std::min(dataWindow.max.y, std::max(dataWindow.min.y, c2.y));
138  c2.z = std::min(dataWindow.max.z, std::max(dataWindow.min.z, c2.z));
139 
140  // Determine which block we're in
141  int i = c1.x, j = c1.y, k = c1.z, vi, vj, vk, bi, bj, bk;
142  field.applyDataWindowOffset(i, j, k);
143  field.getVoxelInBlock(i, j, k, vi, vj, vk);
144  field.getBlockCoord(i, j, k, bi, bj, bk);
145  int blockSize = 1 << field.blockOrder();
146 
147  // If in the middle of a block, optimize lookup stencil
148  if (vi < blockSize - 1 && vj < blockSize - 1 && vk < blockSize - 1) {
149  if (field.blockIsAllocated(bi, bj, bk)) {
150  // Ensure block data is active and kept alive
151  const int blockId = field.blockId(bi, bj, bk);
152  const bool isDynamicLoad = field.isDynamicLoad();
153  if (isDynamicLoad) {
154  field.incBlockRef(blockId);
155  field.activateBlock(blockId);
156  }
157  // Only do work if the block is allocated
158  const Data_T * const p = field.blockData(bi, bj, bk);
159  const Data_T * const c111 =
160  p + vi + vj * blockSize + vk * blockSize * blockSize;
161  const Data_T * const c121 = c111 + blockSize * (c2.y - c1.y);
162  const Data_T * const
163  c112 = c111 + blockSize * blockSize * (c2.z - c1.z);
164  const Data_T * const c122 = c112 + blockSize * (c2.y - c1.y);
165  int xInc = c2.x - c1.x;
166  Data_T value = static_cast<Data_T>
167  (f1.x * (f1.y * (f1.z * *c111 +
168  f2.z * *c112) +
169  f2.y * (f1.z * *c121 +
170  f2.z * *c122)) +
171  f2.x * (f1.y * (f1.z * *(c111 + xInc) +
172  f2.z * *(c112 + xInc)) +
173  f2.y * (f1.z * *(c121 + xInc) +
174  f2.z * *(c122 + xInc))));
175  // Decrement the block ref count
176  if (isDynamicLoad) {
177  field.decBlockRef(blockId);
178  }
179  // Done.
180  return value;
181  } else {
182  return static_cast<Data_T>(field.getBlockEmptyValue(bi, bj, bk));
183  }
184  } else {
185  return static_cast<Data_T>
186  (f1.x * (f1.y * (f1.z * field.fastValue(c1.x, c1.y, c1.z) +
187  f2.z * field.fastValue(c1.x, c1.y, c2.z)) +
188  f2.y * (f1.z * field.fastValue(c1.x, c2.y, c1.z) +
189  f2.z * field.fastValue(c1.x, c2.y, c2.z))) +
190  f2.x * (f1.y * (f1.z * field.fastValue(c2.x, c1.y, c1.z) +
191  f2.z * field.fastValue(c2.x, c1.y, c2.z)) +
192  f2.y * (f1.z * field.fastValue(c2.x, c2.y, c1.z) +
193  f2.z * field.fastValue(c2.x, c2.y, c2.z))));
194  }
195 
196  }
197 
198 private:
199 
200  // Static data members -------------------------------------------------------
201 
203 
204  // Typedefs ------------------------------------------------------------------
205 
207  typedef RefBase base;
208 
209 };
210 
211 //----------------------------------------------------------------------------//
212 
214 
215 //----------------------------------------------------------------------------//
216 // SparseBlock
217 //----------------------------------------------------------------------------//
218 
221 namespace Sparse {
222 
226 template <typename Data_T>
227 struct SparseBlock : boost::noncopyable
228 {
229  // Constructors --------------------------------------------------------------
230 
233  : isAllocated(false),
234  emptyValue(static_cast<Data_T>(0)),
235  data(NULL)
236  { /* Empty */ }
237 
240  {
241  if (data) {
242  delete[] data;
243  }
244  }
245 
246  // Main methods --------------------------------------------------------------
247 
249  inline Data_T& value(int i, int j, int k, int blockOrder)
251  { return data[(k << blockOrder << blockOrder) + (j << blockOrder) + i]; }
252 
255  inline const Data_T& value(int i, int j, int k, int blockOrder) const
256  { return data[(k << blockOrder << blockOrder) + (j << blockOrder) + i]; }
257 
259  void resize(int n)
260  {
261  // First hold lock
262  boost::mutex::scoped_lock lock(ms_resizeMutex);
263  // Perform work
264  if (data) {
265  delete[] data;
266  }
267  data = new Data_T[n];
268  isAllocated = true;
269  std::fill_n(data, n, emptyValue);
270  }
271 
273  void clear()
274  {
275  // First hold lock
276  boost::mutex::scoped_lock lock(ms_resizeMutex);
277  // Perform work
278  if (data) {
279  delete[] data;
280  data = NULL;
281  }
282  }
283 
285  void copy(const SparseBlock &other, size_t n)
286  {
287  if (other.isAllocated) {
288  if (!data) {
289  resize(n);
290  }
291  Data_T *p = data, *end = data + n, *o = other.data;
292  while (p != end) {
293  *p++ = *o++;
294  }
295  } else {
296  clear();
297  }
298  }
299 
300  // Data members --------------------------------------------------------------
301 
304 
308  Data_T emptyValue;
309 
311  Data_T *data;
312 
313 private:
314 
316  SparseBlock(const SparseBlock&);
318  const SparseBlock& operator=(const SparseBlock&);
319 
320  // Data members --------------------------------------------------------------
321 
325  static boost::mutex ms_resizeMutex;
326 
327 };
328 
329 } // namespace Sparse
330 
331 //----------------------------------------------------------------------------//
332 // SparseField
333 //----------------------------------------------------------------------------//
334 
347 //----------------------------------------------------------------------------//
348 
349 template <class Data_T>
351  : public ResizableField<Data_T>
352 {
353 public:
354 
355  // Typedefs ------------------------------------------------------------------
356 
357  typedef boost::intrusive_ptr<SparseField> Ptr;
358  typedef std::vector<Ptr> Vec;
359 
362 
363  // RTTI replacement ----------------------------------------------------------
364 
367 
368  static const char *staticClassName()
369  {
370  return "SparseField";
371  }
372 
373  static const char *staticClassType()
374  {
376  }
377 
378  // Constructors --------------------------------------------------------------
379 
382 
384  SparseField();
385 
387  SparseField(const SparseField &o);
388 
390  ~SparseField();
391 
394  SparseField& operator=(const SparseField &o);
395 
396  // \}
397 
398  // Main methods --------------------------------------------------------------
399 
401  virtual void clear(const Data_T &value);
402 
405  void setBlockOrder(int order);
406 
408  int blockOrder() const;
409 
411  int blockSize() const;
412 
414  bool voxelIsInAllocatedBlock(int i, int j, int k) const;
415 
417  bool blockIsAllocated(int bi, int bj, int bk) const;
418 
421  const Data_T getBlockEmptyValue(int bi, int bj, int bk) const;
422 
425  void setBlockEmptyValue(int bi, int bj, int bk, const Data_T &val);
426 
428  bool blockIndexIsValid(int bi, int bj, int bk) const;
429 
431  V3i blockRes() const;
432 
438  template <typename Functor_T>
439  int releaseBlocks(Functor_T func);
440 
442  int blockId(int blockI, int blockJ, int blockK) const;
443 
447  void getBlockCoord(int i, int j, int k, int &bi, int &bj, int &bk) const;
448 
452  void getVoxelInBlock(int i, int j, int k, int &vi, int &vj, int &vk) const;
453 
455  void applyDataWindowOffset(int &i, int &j, int &k) const
456  {
457  i -= base::m_dataWindow.min.x;
458  j -= base::m_dataWindow.min.y;
459  k -= base::m_dataWindow.min.z;
460  }
461 
463  bool isDynamicLoad() const
464  { return m_fileManager != NULL; }
465 
467  void incBlockRef(const int blockId) const;
468 
470  void activateBlock(const int blockId) const;
471 
473  void decBlockRef(const int blockId) const;
474 
475  // Threading-related ---------------------------------------------------------
476 
478  size_t numGrains() const;
481  bool getGrainBounds(const size_t idx, Box3i &vsBounds) const;
482 
483  // From Field base class -----------------------------------------------------
484 
487  virtual Data_T value(int i, int j, int k) const;
488  virtual long long int memSize() const;
489  virtual size_t voxelCount() const;
491 
492  // From WritableField base class ---------------------------------------------
493 
496  virtual Data_T& lvalue(int i, int j, int k);
498 
499  // Concrete voxel access -----------------------------------------------------
500 
502  Data_T fastValue(int i, int j, int k) const;
504  Data_T& fastLValue(int i, int j, int k);
505 
508  Data_T* blockData(int bi, int bj, int bk) const;
509 
510  // From FieldBase ------------------------------------------------------------
511 
514 
516 
517  virtual FieldBase::Ptr clone() const
518  { return Ptr(new SparseField(*this)); }
519 
521 
522  // Iterators -----------------------------------------------------------------
523 
526 
528  class const_iterator;
529 
531  const_iterator cbegin() const;
533  const_iterator cbegin(const Box3i &subset) const;
535  const_iterator cend() const;
538  const_iterator cend(const Box3i &subset) const;
539 
543  class iterator;
544 
546  iterator begin();
548  iterator begin(const Box3i &subset);
550  iterator end();
553  iterator end(const Box3i &subset);
554 
558  class block_iterator;
559 
560  block_iterator blockBegin() const;
562  block_iterator blockEnd() const;
563 
565 
566  // Internal utility functions ------------------------------------------------
567 
570  void addReference(const std::string &filename, const std::string &layerPath,
571  int valuesPerBlock, int numVoxels, int occupiedBlocks);
574  void setupReferenceBlocks();
575 
576  protected:
577 
578  friend class SparseFieldIO;
579 
580  // Typedefs ------------------------------------------------------------------
581 
584 
585  // From ResizableField class -------------------------------------------------
586 
587  virtual void sizeChanged()
588  {
589  // Call base class
591  setupBlocks();
592  }
593 
594  // Convenience methods -------------------------------------------------------
595 
598 
600  void setupBlocks();
601 
603  void deallocBlock(Block &block, const Data_T &emptyValue);
604 
606 
607  // Data members --------------------------------------------------------------
608 
618  size_t m_numBlocks;
619 
624  int m_fileId;
625 
627  Data_T m_dummy;
628 
629 private:
630 
631  // Static data members -------------------------------------------------------
632 
634 
635  // Utility methods -----------------------------------------------------------
636 
639  void copySparseField(const SparseField &o);
640 
643  void copyBlockStates(const SparseField<Data_T> &o);
644 
645 };
646 
647 //----------------------------------------------------------------------------//
648 // Static member instantiations
649 //----------------------------------------------------------------------------//
650 
652 
653 namespace Sparse {
654 
655 template <typename Data_T>
657 
658 }
659 
660 //----------------------------------------------------------------------------//
661 // Typedefs
662 //----------------------------------------------------------------------------//
663 
670 
671 //------------------------------------------------------------------------------
672 // Helper functions
673 //------------------------------------------------------------------------------
674 
675 template <typename Data_T>
676 Box3i blockCoords(const Box3i &dvsBounds, const SparseField<Data_T> *f)
677 {
678  // Check empty bbox input
679  if (!continuousBounds(dvsBounds).hasVolume()) {
680  return Box3i();
681  }
682  // Discrete offset voxel space
683  Box3i dovsBounds = dvsBounds;
684  f->applyDataWindowOffset(dovsBounds.min.x,
685  dovsBounds.min.y,
686  dovsBounds.min.z);
687  f->applyDataWindowOffset(dovsBounds.max.x,
688  dovsBounds.max.y,
689  dovsBounds.max.z);
690  // Discrete block space bounds
691  Box3i dbsBounds;
692  if (f) {
693  f->getBlockCoord(dovsBounds.min.x, dovsBounds.min.y, dovsBounds.min.z,
694  dbsBounds.min.x, dbsBounds.min.y, dbsBounds.min.z);
695  f->getBlockCoord(dovsBounds.max.x, dovsBounds.max.y, dovsBounds.max.z,
696  dbsBounds.max.x, dbsBounds.max.y, dbsBounds.max.z);
697  }
698  return dbsBounds;
699 }
700 
701 //----------------------------------------------------------------------------//
702 // Helper functors
703 //----------------------------------------------------------------------------//
704 
705 namespace Sparse {
706 
709 template <typename Data_T>
711 {
720  bool check(const SparseBlock<Data_T> &block, Data_T &retEmptyValue,
721  const V3i &validSize, const V3i &blockSize)
722  {
723  // Store first value
724  Data_T first = block.data[0];
725  // Iterate over rest
726  bool match = true;
727  size_t len = blockSize.x * blockSize.y * blockSize.z;
728  if (validSize == blockSize) {
729  // interior block so look at all voxels
730  for (size_t i = 0; i < len; i++) {
731  if (block.data[i] != first) {
732  match = false;
733  break;
734  }
735  }
736  } else {
737  // only look at valid voxels
738  int x=0, y=0, z=0;
739  for (size_t i = 0; i < len; i++, x++) {
740  if (x >= blockSize.x) {
741  x = 0;
742  ++y;
743  if (y >= blockSize.y) {
744  y = 0;
745  ++z;
746  }
747  }
748  if (x >= validSize.x || y >= validSize.y || z >= validSize.z) {
749  continue;
750  }
751  if (block.data[i] != first) {
752  match = false;
753  break;
754  }
755  }
756  } // end of interior block test
757 
758  if (match) {
759  retEmptyValue = first;
760  return true;
761  } else {
762  return false;
763  }
764  }
765 };
766 
767 //----------------------------------------------------------------------------//
768 
769 template <typename Data_T>
770 inline bool isAnyLess(const Data_T &left, const Data_T &right)
771 {
772  return (std::abs(left) < right);
773 }
774 
775 //----------------------------------------------------------------------------//
776 
777 template <>
778 inline bool isAnyLess(const V3h &left, const V3h &right)
779 {
780  return (std::abs(left.x) < right.x ||
781  std::abs(left.y) < right.y ||
782  std::abs(left.z) < right.z );
783 }
784 
785 //----------------------------------------------------------------------------//
786 
787 template <>
788 inline bool isAnyLess(const V3f &left, const V3f &right)
789 {
790  return (std::abs(left.x) < right.x ||
791  std::abs(left.y) < right.y ||
792  std::abs(left.z) < right.z );
793 }
794 
795 //----------------------------------------------------------------------------//
796 
797 template <>
798 inline bool isAnyLess(const V3d &left, const V3d &right)
799 {
800  return (std::abs(left.x) < right.x ||
801  std::abs(left.y) < right.y ||
802  std::abs(left.z) < right.z );
803 }
804 
805 //----------------------------------------------------------------------------//
806 
810 template <typename Data_T>
812 {
814  CheckMaxAbs(Data_T maxValue)
815  : m_maxValue(maxValue)
816  { }
825  bool check(const SparseBlock<Data_T> &block, Data_T &retEmptyValue,
826  const V3i &validSize, const V3i &blockSize)
827  {
828  // Store first value
829  Data_T first = block.data[0];
830  // Iterate over rest
831  bool allGreater = true;
832  size_t len = blockSize.x * blockSize.y * blockSize.z;
833 
834  if (validSize == blockSize) {
835  // interior block so look at all voxels
836  for (size_t i = 0; i < len; i++) {
837  if (isAnyLess<Data_T>(block.data[i], m_maxValue)) {
838  allGreater = false;
839  break;
840  }
841  }
842  } else {
843  // only look at valid voxels
844  int x=0, y=0, z=0;
845  for (size_t i = 0; i < len; i++, x++) {
846  if (x >= blockSize.x) {
847  x = 0;
848  ++y;
849  if (y >= blockSize.y) {
850  y = 0;
851  ++z;
852  }
853  }
854  if (x >= validSize.x || y >= validSize.y || z >= validSize.z) {
855  continue;
856  }
857  if (isAnyLess<Data_T>(block.data[i], m_maxValue)) {
858  allGreater = false;
859  break;
860  }
861  }
862  } // end of interior block test
863 
864  if (allGreater) {
865  retEmptyValue = first;
866  return true;
867  } else {
868  return false;
869  }
870  }
871 private:
872  Data_T m_maxValue;
873 };
874 
875 //----------------------------------------------------------------------------//
876 
877 } // namespace Sparse
878 
879 //----------------------------------------------------------------------------//
880 // SparseField::const_iterator
881 //----------------------------------------------------------------------------//
882 
884 template <class Data_T>
886 {
887  public:
888 #if defined(WIN32) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
889  typedef std::forward_iterator_tag iterator_category;
890  typedef Data_T value_type;
891  typedef ptrdiff_t difference_type;
892  typedef ptrdiff_t distance_type;
893  typedef Data_T *pointer;
894  typedef Data_T& reference;
895 #endif
896 
899  const Box3i &window,
900  const V3i &currentPos, int blockOrder)
901  : x(currentPos.x), y(currentPos.y), z(currentPos.z),
902  m_p(NULL), m_blockIsActivated(false),
903  m_blockStepsTicker(0), m_blockOrder(blockOrder),
904  m_blockId(-1), m_window(window), m_field(&field)
905  {
906  m_manager = m_field->m_fileManager;
907  setupNextBlock(x, y, z);
908  }
910  if (m_manager && m_blockId >= 0 &&
911  m_blockId < static_cast<int>(m_field->m_numBlocks)) {
912  if (m_field->m_blocks[m_blockId].isAllocated)
913  m_manager->decBlockRef<Data_T>(m_field->m_fileId, m_blockId);
914  }
915  }
916  const const_iterator& operator ++ ()
917  {
918  bool resetPtr = false;
919  // Check against end of data window
920  if (x == m_window.max.x) {
921  if (y == m_window.max.y) {
922  x = m_window.min.x;
923  y = m_window.min.y;
924  ++z;
925  resetPtr = true;
926  } else {
927  x = m_window.min.x;
928  ++y;
929  resetPtr = true;
930  }
931  } else {
932  ++x;
933  }
934  // These can both safely be incremented here
935  ++m_blockStepsTicker;
936  // ... but only step forward if we're in a non-empty block
937  if (!m_isEmptyBlock && (!m_manager || m_blockIsActivated))
938  ++m_p;
939  // Check if we've reached the end of this block
940  if (m_blockStepsTicker == (1 << m_blockOrder))
941  resetPtr = true;
942  if (resetPtr) {
943  // If we have, we need to reset the current block, etc.
944  m_blockStepsTicker = 0;
945  setupNextBlock(x, y, z);
946  }
947  return *this;
948  }
949  template <class Iter_T>
950  inline bool operator == (const Iter_T &rhs) const
951  {
952  return x == rhs.x && y == rhs.y && z == rhs.z;
953  }
954  template <class Iter_T>
955  inline bool operator != (const Iter_T &rhs) const
956  {
957  return x != rhs.x || y != rhs.y || z != rhs.z;
958  }
959  inline const Data_T& operator * () const
960  {
961  if (!m_isEmptyBlock && m_manager && !m_blockIsActivated) {
962  m_manager->activateBlock<Data_T>(m_field->m_fileId, m_blockId);
963  m_blockIsActivated = true;
964  const Block &block = m_field->m_blocks[m_blockId];
965  int vi, vj, vk;
966  m_field->getVoxelInBlock(x, y, z, vi, vj, vk);
967  m_p = &block.value(vi, vj, vk, m_blockOrder);
968  }
969  return *m_p;
970  }
971  inline const Data_T* operator -> () const
972  {
973  if (!m_isEmptyBlock && m_manager && !m_blockIsActivated) {
974  SparseFileManager *manager = m_field->m_fileManager;
975  manager->activateBlock<Data_T>(m_field->m_fileId, m_blockId);
976  m_blockIsActivated = true;
977  const Block &block = m_field->m_blocks[m_blockId];
978  int vi, vj, vk;
979  m_field->getVoxelInBlock(x, y, z, vi, vj, vk);
980  m_p = &block.value(vi, vj, vk, m_blockOrder);
981  }
982  return m_p;
983  }
984 
985  // Public data members -------------------------------------------------------
986 
988  int x, y, z;
989 
990 private:
991 
992  // Typedefs ------------------------------------------------------------------
993 
995 
996  // Convenience methods -------------------------------------------------------
997 
998  void setupNextBlock(int i, int j, int k)
999  {
1000  m_field->applyDataWindowOffset(i, j, k);
1001  m_field->getBlockCoord(i, j, k, m_blockI, m_blockJ, m_blockK);
1002  int oldBlockId = m_blockId;
1003  m_blockId = m_field->blockId(m_blockI, m_blockJ, m_blockK);
1004  if (m_manager && oldBlockId != m_blockId &&
1005  oldBlockId >= 0 &&
1006  oldBlockId < static_cast<int>(m_field->m_numBlocks) &&
1007  m_field->m_blocks[oldBlockId].isAllocated) {
1008  m_manager->decBlockRef<Data_T>(m_field->m_fileId, oldBlockId);
1009  }
1010  if (m_blockId >= m_field->m_blockXYSize * m_field->m_blockRes.z) {
1011  m_isEmptyBlock = true;
1012  return;
1013  }
1014 
1015  const Block &block = m_field->m_blocks[m_blockId];
1016  int vi, vj, vk;
1017  m_field->getVoxelInBlock(i, j, k, vi, vj, vk);
1018  m_blockStepsTicker = vi;
1019  if (block.isAllocated) {
1020  if (m_manager && oldBlockId != m_blockId && m_blockId >= 0) {
1021  m_manager->incBlockRef<Data_T>(m_field->m_fileId, m_blockId);
1022  // this is a managed field, so the block may not be loaded
1023  // yet, so don't bother setting m_p yet (it'll get set in the
1024  // * and -> operators when the block is activated)
1025  } else {
1026  // only set m_p to the voxel's address if this is not a
1027  // managed field, i.e., if the data is already in memory.
1028  m_p = &block.value(vi, vj, vk, m_blockOrder);
1029  }
1030  m_isEmptyBlock = false;
1031  } else {
1032  m_p = &block.emptyValue;
1033  m_isEmptyBlock = true;
1034  }
1035  if (m_field->m_fileManager) {
1036  m_blockIsActivated = false;
1037  }
1038  }
1039 
1041  mutable const Data_T *m_p;
1046  mutable bool m_blockIsActivated;
1052  int m_blockI, m_blockJ, m_blockK, m_blockId;
1059 };
1060 
1061 //----------------------------------------------------------------------------//
1062 // SparseField::iterator
1063 //----------------------------------------------------------------------------/
1064 
1066 template <class Data_T>
1067 class SparseField<Data_T>::iterator
1068 {
1069  public:
1070 #if defined(WIN32) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
1071  typedef std::forward_iterator_tag iterator_category;
1072  typedef Data_T value_type;
1073  typedef ptrdiff_t difference_type;
1074  typedef ptrdiff_t distance_type;
1075  typedef Data_T *pointer;
1076  typedef Data_T& reference;
1077 #endif
1078 
1081  const Box3i &window,
1082  const V3i &currentPos, int blockOrder)
1083  : x(currentPos.x), y(currentPos.y), z(currentPos.z),
1084  m_p(NULL), m_blockStepsTicker(0), m_blockOrder(blockOrder),
1085  m_blockId(-1), m_window(window), m_field(&field)
1086  {
1087  setupNextBlock(x, y, z);
1088  }
1089  const iterator& operator ++ ()
1090  {
1091  bool resetPtr = false;
1092  // Check against end of data window
1093  if (x == m_window.max.x) {
1094  if (y == m_window.max.y) {
1095  x = m_window.min.x;
1096  y = m_window.min.y;
1097  ++z;
1098  resetPtr = true;
1099  } else {
1100  x = m_window.min.x;
1101  ++y;
1102  resetPtr = true;
1103  }
1104  } else {
1105  ++x;
1106  }
1107  // These can both safely be incremented here
1108  ++m_blockStepsTicker;
1109  // ... but only step forward if we're in a non-empty block
1110  if (!m_isEmptyBlock)
1111  ++m_p;
1112  // Check if we've reached the end of this block
1113  if (m_blockStepsTicker == (1 << m_blockOrder))
1114  resetPtr = true;
1115  if (resetPtr) {
1116  // If we have, we need to reset the current block, etc.
1117  m_blockStepsTicker = 0;
1118  setupNextBlock(x, y, z);
1119  }
1120  return *this;
1121  }
1122  inline bool operator == (const iterator &rhs) const
1123  {
1124  return x == rhs.x && y == rhs.y && z == rhs.z;
1125  }
1126  inline bool operator != (const iterator &rhs) const
1127  {
1128  return x != rhs.x || y != rhs.y || z != rhs.z;
1129  }
1130  inline Data_T& operator * ()
1131  {
1132  if (m_field->m_fileManager) {
1133  assert(false && "Dereferencing iterator on a dynamic-read sparse field");
1134  Msg::print(Msg::SevWarning, "Dereferencing iterator on a dynamic-read "
1135  "sparse field");
1136  return *m_p;
1137  }
1138  // If the block is currently empty, we must allocate it
1139  if (m_isEmptyBlock) {
1140  // Touch the voxel to allocate the block
1141  m_field->lvalue(x, y, z);
1142  // Set up the block again
1143  setupNextBlock(x, y, z);
1144  }
1145  return *m_p;
1146  }
1147  inline Data_T* operator -> ()
1148  {
1149  if (m_field->m_fileManager) {
1150  assert(false && "Dereferencing iterator on a dynamic-read sparse field");
1151  Msg::print(Msg::SevWarning, "Dereferencing iterator on a dynamic-read "
1152  "sparse field");
1153  return m_p;
1154  }
1155  // If the block is currently empty, we must allocate it
1156  if (m_isEmptyBlock) {
1157  // Touch the voxel to allocate the block
1158  m_field->lvalue(x, y, z);
1159  // Set up the block again
1160  setupNextBlock(x, y, z);
1161  }
1162  return m_p;
1163  }
1164  // Public data members
1165  int x, y, z;
1166 private:
1169  void setupNextBlock(int i, int j, int k)
1170  {
1171  m_field->applyDataWindowOffset(i, j, k);
1172  m_field->getBlockCoord(i, j, k, m_blockI, m_blockJ, m_blockK);
1173  m_blockId = m_field->blockId(m_blockI, m_blockJ, m_blockK);
1174  if (m_blockId >= m_field->m_blockXYSize * m_field->m_blockRes.z) {
1175  m_isEmptyBlock = true;
1176  return;
1177  }
1178  Block &block = m_field->m_blocks[m_blockId];
1179  int vi, vj, vk;
1180  m_field->getVoxelInBlock(i, j, k, vi, vj, vk);
1181  m_blockStepsTicker = vi;
1182  if (block.isAllocated) {
1183  m_p = &block.value(vi, vj, vk, m_blockOrder);
1184  m_isEmptyBlock = false;
1185  } else {
1186  m_p = &block.emptyValue;
1187  m_isEmptyBlock = true;
1188  }
1189  }
1191  Data_T *m_p;
1199  int m_blockI, m_blockJ, m_blockK, m_blockId;
1204 };
1205 
1206 //----------------------------------------------------------------------------//
1207 // SparseField::block_iterator
1208 //----------------------------------------------------------------------------/
1209 
1212 template <class Data_T>
1214 {
1215  public:
1219  block_iterator(const class_type &field, const Box3i &window,
1220  const V3i &currentPos)
1221  : x(currentPos.x), y(currentPos.y), z(currentPos.z),
1222  m_window(window), m_field(field)
1223  {
1224  recomputeBlockBoundingBox();
1225  }
1227  const block_iterator& operator ++ ()
1228  {
1229  if (x == m_window.max.x) {
1230  if (y == m_window.max.y) {
1231  x = m_window.min.x;
1232  y = m_window.min.y;
1233  ++z;
1234  } else {
1235  x = m_window.min.x;
1236  ++y;
1237  }
1238  } else {
1239  ++x;
1240  }
1241  recomputeBlockBoundingBox();
1242  return *this;
1243  }
1245  inline bool operator == (const block_iterator &rhs) const
1246  {
1247  return x == rhs.x && y == rhs.y && z == rhs.z;
1248  }
1250  inline bool operator != (const block_iterator &rhs) const
1251  {
1252  return x != rhs.x || y != rhs.y || z != rhs.z;
1253  }
1256  {
1257  return m_currentBlockWindow;
1258  }
1260  int x, y, z;
1261 private:
1263  {
1264  Box3i box;
1265  int blockSize = m_field.blockSize();
1266  box.min = V3i(x * blockSize, y * blockSize, z * blockSize);
1267  box.max = box.min + V3i(blockSize - 1, blockSize - 1, blockSize - 1);
1268  // Clamp the box
1269  box.min = FIELD3D_CLIP(box.min, m_field.dataWindow());
1270  box.max = FIELD3D_CLIP(box.max, m_field.dataWindow());
1271  // Set the member variable
1272  m_currentBlockWindow = box;
1273  }
1280 };
1281 
1282 //----------------------------------------------------------------------------//
1283 // SparseField implementations
1284 //----------------------------------------------------------------------------//
1285 
1286 template <class Data_T>
1288  : base(),
1289  m_blockOrder(BLOCK_ORDER),
1290  m_blocks(NULL),
1291  m_fileManager(NULL)
1292 {
1293  setupBlocks();
1294 }
1295 
1296 //----------------------------------------------------------------------------//
1297 
1298 template <class Data_T>
1300  : base(o),
1301  m_blockOrder(o.m_blockOrder),
1302  m_blocks(NULL),
1303  m_fileManager(o.m_fileManager)
1304 {
1305  copySparseField(o);
1306 }
1307 
1308 //----------------------------------------------------------------------------//
1309 
1310 template <class Data_T>
1312 {
1313  if (m_fileManager) {
1314  // this file is dynamically managed, so we need to ensure the
1315  // cache doesn't point to this field's blocks because they are
1316  // about to be deleted
1317  m_fileManager->removeFieldFromCache<Data_T>(m_fileId);
1318  }
1319  if (m_blocks) {
1320  delete[] m_blocks;
1321  }
1322 }
1323 
1324 //----------------------------------------------------------------------------//
1325 
1326 template <class Data_T>
1329 {
1330  if (this != &o) {
1331  this->base::operator=(o);
1332  copySparseField(o);
1333  }
1334  return *this;
1335 }
1336 
1337 //----------------------------------------------------------------------------//
1338 
1339 template <class Data_T>
1340 void
1342 {
1343  m_blockOrder = o.m_blockOrder;
1344  if (o.m_fileManager) {
1345  // allocate m_blocks, sets m_blockRes, m_blockXYSize, m_blocks
1346  setupBlocks();
1347  m_fileManager = o.m_fileManager;
1348  SparseFile::Reference<Data_T> *oldReference =
1349  m_fileManager->reference<Data_T>(o.m_fileId);
1350  addReference(oldReference->filename, oldReference->layerPath,
1351  oldReference->valuesPerBlock,
1352  oldReference->numVoxels,
1353  oldReference->occupiedBlocks);
1354  copyBlockStates(o);
1355  setupReferenceBlocks();
1356  } else {
1357  // directly copy all values and blocks from the source, no extra setup
1358  m_blockRes = o.m_blockRes;
1359  m_blockXYSize = o.m_blockXYSize;
1360  if (m_blocks) {
1361  delete[] m_blocks;
1362  }
1363  m_numBlocks = o.m_numBlocks;
1364  m_blocks = new Block[m_numBlocks];
1365  for (size_t i = 0; i < m_numBlocks; ++i) {
1366  m_blocks[i].isAllocated = o.m_blocks[i].isAllocated;
1367  m_blocks[i].emptyValue = o.m_blocks[i].emptyValue;
1368  m_blocks[i].copy(o.m_blocks[i],
1369  1 << m_blockOrder << m_blockOrder << m_blockOrder);
1370  }
1371  m_fileId = -1;
1372  m_fileManager = NULL;
1373  }
1374 }
1375 
1376 //----------------------------------------------------------------------------//
1377 
1378 template <class Data_T>
1379 void SparseField<Data_T>::addReference(const std::string &filename,
1380  const std::string &layerPath,
1381  int valuesPerBlock,
1382  int numVoxels,
1383  int occupiedBlocks)
1384 {
1385  m_fileManager = &SparseFileManager::singleton();
1386  m_fileId = m_fileManager->getNextId<Data_T>(filename, layerPath);
1387  // Set up the manager data
1388  SparseFile::Reference<Data_T> *reference =
1389  m_fileManager->reference<Data_T>(m_fileId);
1390  reference->valuesPerBlock = valuesPerBlock;
1391  reference->numVoxels = numVoxels;
1392  reference->occupiedBlocks = occupiedBlocks;
1393  reference->setNumBlocks(m_numBlocks);
1394 }
1395 
1396 //----------------------------------------------------------------------------//
1397 
1398 template <class Data_T>
1400 {
1401  if (m_numBlocks != o.m_numBlocks) return;
1402 
1403  for (size_t i = 0; i < m_numBlocks; ++i) {
1404  m_blocks[i].isAllocated = o.m_blocks[i].isAllocated;
1405  m_blocks[i].emptyValue = o.m_blocks[i].emptyValue;
1406  m_blocks[i].clear();
1407  }
1408 }
1409 
1410 //----------------------------------------------------------------------------//
1411 
1412 template <class Data_T>
1414 {
1415  if (!m_fileManager || m_fileId < 0) return;
1416 
1417  SparseFile::Reference<Data_T> *reference =
1418  m_fileManager->reference<Data_T>(m_fileId);
1419 
1420 #if F3D_NO_BLOCKS_ARRAY
1421  std::vector<int>::iterator fb = reference->fileBlockIndices.begin();
1422  reference->blocks = m_blocks;
1423  int nextBlockIdx = 0;
1424  for (size_t i = 0; i < m_numBlocks; ++i, ++fb) {
1425  if (m_blocks[i].isAllocated) {
1426  *fb = nextBlockIdx;
1427  nextBlockIdx++;
1428  } else {
1429  *fb = -1;
1430  }
1431  }
1432 #else
1433  std::vector<int>::iterator fb = reference->fileBlockIndices.begin();
1435  reference->blocks.begin();
1436  int nextBlockIdx = 0;
1437  for (size_t i = 0; i < m_numBlocks; ++i, ++fb, ++bp) {
1438  if (m_blocks[i].isAllocated) {
1439  *fb = nextBlockIdx;
1440  *bp = m_blocks + i;
1441  nextBlockIdx++;
1442  } else {
1443  *fb = -1;
1444  }
1445  }
1446 #endif
1447 }
1448 
1449 //----------------------------------------------------------------------------//
1450 
1451 template <class Data_T>
1452 void SparseField<Data_T>::clear(const Data_T &value)
1453 {
1454  // If we're clearing, we can get rid of all current blocks
1455  setupBlocks();
1456  Block *p = m_blocks, *end = m_blocks + m_numBlocks;
1457  while (p != end) {
1458  p->emptyValue = value;
1459  ++p;
1460  }
1461 }
1462 
1463 //----------------------------------------------------------------------------//
1464 
1465 template <class Data_T>
1467 {
1468  m_blockOrder = order;
1469  setupBlocks();
1470 }
1471 
1472 //----------------------------------------------------------------------------//
1473 
1474 template <class Data_T>
1476 {
1477  return m_blockOrder;
1478 }
1479 
1480 //----------------------------------------------------------------------------//
1481 
1482 template <class Data_T>
1484 {
1485  return 1 << m_blockOrder;
1486 }
1487 
1488 //----------------------------------------------------------------------------//
1489 
1490 template <class Data_T>
1491 bool SparseField<Data_T>::voxelIsInAllocatedBlock(int i, int j, int k) const
1492 {
1493  int bi, bj, bk;
1494  applyDataWindowOffset(i, j, k);
1495  getBlockCoord(i, j, k, bi, bj, bk);
1496  return blockIsAllocated(bi, bj, bk);
1497 }
1498 
1499 //----------------------------------------------------------------------------//
1500 
1501 template <class Data_T>
1502 bool SparseField<Data_T>::blockIsAllocated(int bi, int bj, int bk) const
1503 {
1504  const Block &block = m_blocks[blockId(bi, bj, bk)];
1505  return block.isAllocated;
1506 }
1507 
1508 //----------------------------------------------------------------------------//
1509 
1510 template <class Data_T>
1511 const Data_T SparseField<Data_T>::getBlockEmptyValue(int bi, int bj, int bk) const
1512 {
1513  return m_blocks[blockId(bi, bj, bk)].emptyValue;
1514 }
1515 
1516 //----------------------------------------------------------------------------//
1517 
1518 template <class Data_T>
1519 void SparseField<Data_T>::setBlockEmptyValue(int bi, int bj, int bk,
1520  const Data_T &val)
1521 {
1522  Block &block = m_blocks[blockId(bi, bj, bk)];
1523  if (block.isAllocated) {
1524  deallocBlock(block, val);
1525  } else {
1526  block.emptyValue = val;
1527  }
1528 }
1529 
1530 //----------------------------------------------------------------------------//
1531 
1532 template <class Data_T>
1533 bool SparseField<Data_T>::blockIndexIsValid(int bi, int bj, int bk) const
1534 {
1535  return bi >= 0 && bj >= 0 && bk >= 0 &&
1536  bi < m_blockRes.x && bj < m_blockRes.y && bk < m_blockRes.z;
1537 }
1538 
1539 //----------------------------------------------------------------------------//
1540 
1541 template <class Data_T>
1543 {
1544  return m_blockRes;
1545 }
1546 
1547 //----------------------------------------------------------------------------//
1548 
1549 template <class Data_T>
1550 template <typename Functor_T>
1552 {
1553  Data_T emptyValue;
1554  int numDeallocs = 0;
1555 
1556  // If the block is on the edge of the field, it may have unused
1557  // voxels, with undefined values. We need to pass the range of
1558  // valid voxels into the check function, so it only looks at valid
1559  // voxels.
1560  V3i dataRes = FieldRes::dataResolution();
1561  V3i validSize;
1562  V3i blockAllocSize(blockSize());
1563 
1564  int bx = 0, by = 0, bz = 0;
1565  for (size_t i = 0; i < m_numBlocks; ++i, ++bx) {
1566  if (bx >= m_blockRes.x) {
1567  bx = 0;
1568  ++by;
1569  if (by >= m_blockRes.y) {
1570  by = 0;
1571  ++bz;
1572  }
1573  }
1574  validSize = blockAllocSize;
1575  if (bx == m_blockRes.x-1) {
1576  validSize.x = dataRes.x - bx * blockAllocSize.x;
1577  }
1578  if (by == m_blockRes.y-1) {
1579  validSize.y = dataRes.y - by * blockAllocSize.y;
1580  }
1581  if (bz == m_blockRes.z-1) {
1582  validSize.z = dataRes.z - bz * blockAllocSize.z;
1583  }
1584 
1585  if (m_blocks[i].isAllocated) {
1586  if (func.check(m_blocks[i], emptyValue, validSize, blockAllocSize)) {
1587  deallocBlock(m_blocks[i], emptyValue);
1588  numDeallocs++;
1589  }
1590  }
1591  }
1592  return numDeallocs;
1593 }
1594 
1595 //----------------------------------------------------------------------------//
1596 
1597 template <class Data_T>
1598 Data_T SparseField<Data_T>::value(int i, int j, int k) const
1599 {
1600  return fastValue(i, j, k);
1601 }
1602 
1603 //----------------------------------------------------------------------------//
1604 
1605 template <class Data_T>
1606 Data_T& SparseField<Data_T>::lvalue(int i, int j, int k)
1607 {
1608  return fastLValue(i, j, k);
1609 }
1610 
1611 //----------------------------------------------------------------------------//
1612 
1613 template <class Data_T>
1614 Data_T SparseField<Data_T>::fastValue(int i, int j, int k) const
1615 {
1616  assert (i >= base::m_dataWindow.min.x);
1617  assert (i <= base::m_dataWindow.max.x);
1618  assert (j >= base::m_dataWindow.min.y);
1619  assert (j <= base::m_dataWindow.max.y);
1620  assert (k >= base::m_dataWindow.min.z);
1621  assert (k <= base::m_dataWindow.max.z);
1622  // Add crop window offset
1623  applyDataWindowOffset(i, j, k);
1624  // Find block coord
1625  int bi, bj, bk;
1626  getBlockCoord(i, j, k, bi, bj, bk);
1627  // Find coord in block
1628  int vi, vj, vk;
1629  getVoxelInBlock(i, j, k, vi, vj, vk);
1630  // Get the actual block
1631  int id = blockId(bi, bj, bk);
1632  const Block &block = m_blocks[id];
1633  // Check if block data is allocated
1634  if (block.isAllocated) {
1635  if (m_fileManager) {
1636  m_fileManager->incBlockRef<Data_T>(m_fileId, id);
1637  m_fileManager->activateBlock<Data_T>(m_fileId, id);
1638  Data_T tmpValue = block.value(vi, vj, vk, m_blockOrder);
1639  m_fileManager->decBlockRef<Data_T>(m_fileId, id);
1640  return tmpValue;
1641  } else {
1642  return block.value(vi, vj, vk, m_blockOrder);
1643  }
1644  } else {
1645  return block.emptyValue;
1646  }
1647 }
1648 
1649 //----------------------------------------------------------------------------//
1650 
1652 template <class Data_T>
1653 Data_T& SparseField<Data_T>::fastLValue(int i, int j, int k)
1654 {
1655  assert (i >= base::m_dataWindow.min.x);
1656  assert (i <= base::m_dataWindow.max.x);
1657  assert (j >= base::m_dataWindow.min.y);
1658  assert (j <= base::m_dataWindow.max.y);
1659  assert (k >= base::m_dataWindow.min.z);
1660  assert (k <= base::m_dataWindow.max.z);
1661 
1662  if (m_fileManager) {
1663  assert(false && "Called fastLValue() on a dynamic-read sparse field");
1664  Msg::print(Msg::SevWarning, "Called fastLValue() on a dynamic-read "
1665  "sparse field");
1666  return m_dummy;
1667  }
1668 
1669  // Add crop window offset
1670  applyDataWindowOffset(i, j, k);
1671  // Find block coord
1672  int bi, bj, bk;
1673  getBlockCoord(i, j, k, bi, bj, bk);
1674  // Find coord in block
1675  int vi, vj, vk;
1676  getVoxelInBlock(i, j, k, vi, vj, vk);
1677  // Get the actual block
1678  int id = blockId(bi, bj, bk);
1679  Block &block = m_blocks[id];
1680  // If block is allocated, return a reference to the data
1681  if (block.isAllocated) {
1682  return block.value(vi, vj, vk, m_blockOrder);
1683  } else {
1684  // ... Otherwise, allocate block
1685  size_t blockSize = 1 << m_blockOrder << m_blockOrder << m_blockOrder;
1686  block.resize(blockSize);
1687  return block.value(vi, vj, vk, m_blockOrder);
1688  }
1689 }
1690 
1691 //----------------------------------------------------------------------------//
1692 
1693 template <class Data_T>
1694 Data_T* SparseField<Data_T>::blockData(int bi, int bj, int bk) const
1695 {
1696  int id = blockId(bi, bj, bk);
1697  const Block &block = m_blocks[id];
1698  if (block.isAllocated) {
1699  return block.data;
1700  } else {
1701  return NULL;
1702  }
1703 }
1704 
1705 //----------------------------------------------------------------------------//
1706 
1707 template <class Data_T>
1708 long long int SparseField<Data_T>::memSize() const
1709 {
1710  long long int blockSize = m_numBlocks * sizeof(Block);
1711  long long int dataSize = 0;
1712 
1713  for (size_t i = 0; i < m_numBlocks; ++i) {
1714  if (m_blocks[i].data) {
1715  dataSize += (1 << m_blockOrder << m_blockOrder << m_blockOrder) *
1716  sizeof(Data_T);
1717  }
1718  }
1719 
1720  return sizeof(*this) + dataSize + blockSize;
1721 }
1722 
1723 //----------------------------------------------------------------------------//
1724 
1725 template <class Data_T>
1727 {
1728  size_t count = 0;
1729  const size_t blockSize = (1 << m_blockOrder << m_blockOrder << m_blockOrder);
1730 
1731  for (size_t i = 0; i < m_numBlocks; ++i) {
1732  if (m_blocks[i].isAllocated) {
1733  count += blockSize;
1734  }
1735  }
1736 
1737  return count;
1738 }
1739 
1740 //----------------------------------------------------------------------------//
1741 
1742 template <class Data_T>
1745 {
1746  if (FieldRes::dataResolution() == V3i(0))
1747  return cend();
1748  return const_iterator(*this, base::m_dataWindow, base::m_dataWindow.min,
1749  m_blockOrder);
1750 }
1751 
1752 //----------------------------------------------------------------------------//
1753 
1754 template <class Data_T>
1757 {
1758  if (subset.isEmpty())
1759  return cend(subset);
1760  return const_iterator(*this, subset, subset.min, m_blockOrder);
1761 }
1762 
1763 //----------------------------------------------------------------------------//
1764 
1765 template <class Data_T>
1768 {
1769  return const_iterator(*this, base::m_dataWindow,
1770  V3i(base::m_dataWindow.min.x,
1771  base::m_dataWindow.min.y,
1772  base::m_dataWindow.max.z + 1),
1773  m_blockOrder);
1774 }
1775 
1776 //----------------------------------------------------------------------------//
1777 
1778 template <class Data_T>
1780 SparseField<Data_T>::cend(const Box3i &subset) const
1781 {
1782  return const_iterator(*this, subset,
1783  V3i(subset.min.x,
1784  subset.min.y,
1785  subset.max.z + 1), m_blockOrder);
1786 }
1787 
1788 //----------------------------------------------------------------------------//
1789 
1790 template <class Data_T>
1793 {
1794  if (FieldRes::dataResolution() == V3i(0))
1795  return end();
1796  return iterator(*this, base::m_dataWindow,
1797  base::m_dataWindow.min, m_blockOrder); }
1798 
1799 //----------------------------------------------------------------------------//
1800 
1801 template <class Data_T>
1804 {
1805  if (subset.isEmpty())
1806  return end(subset);
1807  return iterator(*this, subset, subset.min, m_blockOrder);
1808 }
1809 
1810 //----------------------------------------------------------------------------//
1811 
1812 template <class Data_T>
1815 {
1816  return iterator(*this, base::m_dataWindow,
1817  V3i(base::m_dataWindow.min.x,
1818  base::m_dataWindow.min.y,
1819  base::m_dataWindow.max.z + 1), m_blockOrder);
1820 }
1821 
1822 //----------------------------------------------------------------------------//
1823 
1824 template <class Data_T>
1827 {
1828  return iterator(*this, subset,
1829  V3i(subset.min.x, subset.min.y, subset.max.z + 1),
1830  m_blockOrder);
1831 }
1832 
1833 //----------------------------------------------------------------------------//
1834 
1835 template <class Data_T>
1838 {
1839  if (FieldRes::dataResolution() == V3i(0))
1840  return blockEnd();
1841  return block_iterator(*this, Box3i(V3i(0), m_blockRes - V3i(1)),
1842  V3i(0));
1843 }
1844 
1845 //----------------------------------------------------------------------------//
1846 
1847 template <class Data_T>
1850 {
1851  return block_iterator(*this, Box3i(V3i(0), m_blockRes - V3i(1)),
1852  V3i(0, 0, m_blockRes.z));
1853 }
1854 
1855 //----------------------------------------------------------------------------//
1856 
1857 template <class Data_T>
1859 {
1860  // Do calculation in floating point so we can round up later
1861  V3f res(base::m_dataWindow.size() + V3i(1));
1862  V3f blockRes(res / (1 << m_blockOrder));
1863  blockRes.x = ceil(blockRes.x);
1864  blockRes.y = ceil(blockRes.y);
1865  blockRes.z = ceil(blockRes.z);
1866  V3i intBlockRes(static_cast<int>(blockRes.x),
1867  static_cast<int>(blockRes.y),
1868  static_cast<int>(blockRes.z));
1869  m_blockRes = intBlockRes;
1870  m_blockXYSize = m_blockRes.x * m_blockRes.y;
1871  if (m_blocks) {
1872  delete[] m_blocks;
1873  }
1874  m_numBlocks = intBlockRes.x * intBlockRes.y * intBlockRes.z;
1875  m_blocks = new Block[m_numBlocks];
1876 }
1877 
1878 //----------------------------------------------------------------------------//
1879 
1880 template <class Data_T>
1881 int SparseField<Data_T>::blockId(int blockI, int blockJ, int blockK) const
1882 {
1883  return blockK * m_blockXYSize + blockJ * m_blockRes.x + blockI;
1884 }
1885 
1886 //----------------------------------------------------------------------------//
1887 
1889 template <class Data_T>
1890 void SparseField<Data_T>::getBlockCoord(int i, int j, int k,
1891  int &bi, int &bj, int &bk) const
1892 {
1893  assert(i >= 0);
1894  assert(j >= 0);
1895  assert(k >= 0);
1896  bi = i >> m_blockOrder;
1897  bj = j >> m_blockOrder;
1898  bk = k >> m_blockOrder;
1899 }
1900 
1901 //----------------------------------------------------------------------------//
1902 
1904 template <class Data_T>
1905 void SparseField<Data_T>::getVoxelInBlock(int i, int j, int k,
1906  int &vi, int &vj, int &vk) const
1907 {
1908  assert(i >= 0);
1909  assert(j >= 0);
1910  assert(k >= 0);
1911  vi = i & ((1 << m_blockOrder) - 1);
1912  vj = j & ((1 << m_blockOrder) - 1);
1913  vk = k & ((1 << m_blockOrder) - 1);
1914 }
1915 
1916 //----------------------------------------------------------------------------//
1917 
1918 template <class Data_T>
1919 void SparseField<Data_T>::incBlockRef(const int blockId) const
1920 {
1921  m_fileManager->incBlockRef<Data_T>(m_fileId, blockId);
1922 }
1923 
1924 //----------------------------------------------------------------------------//
1925 
1926 template <class Data_T>
1927 void SparseField<Data_T>::activateBlock(const int blockId) const
1928 {
1929  m_fileManager->activateBlock<Data_T>(m_fileId, blockId);
1930 }
1931 
1932 //----------------------------------------------------------------------------//
1933 
1934 template <class Data_T>
1935 void SparseField<Data_T>::decBlockRef(const int blockId) const
1936 {
1937  m_fileManager->decBlockRef<Data_T>(m_fileId, blockId);
1938 }
1939 
1940 //----------------------------------------------------------------------------//
1941 
1942 template <class Data_T>
1944 {
1945  return m_numBlocks;
1946 }
1947 
1948 //----------------------------------------------------------------------------//
1949 
1950 template <class Data_T>
1951 bool SparseField<Data_T>::getGrainBounds(const size_t idx, Box3i &bounds) const
1952 {
1953  // Block size
1954  const size_t blockSide = (1 << m_blockOrder);
1955  // Block coordinate
1956  const V3i bCoord = indexToCoord(idx, m_blockRes);
1957  // Block bbox
1958  const V3i start(bCoord * blockSide + base::m_dataWindow.min);
1959  const V3i end (start + Imath::V3i(blockSide - 1));
1960  // Bounds must be clipped against data window
1961  const Box3i unclipped(start, end);
1962  bounds = clipBounds(unclipped, base::m_dataWindow);
1963  // Whether it's a contiguous block
1964  return bounds == unclipped;
1965 }
1966 
1967 //----------------------------------------------------------------------------//
1968 
1969 template <class Data_T>
1970 void SparseField<Data_T>::deallocBlock(Block &block, const Data_T &emptyValue)
1971 {
1972  block.isAllocated = false;
1974  block.clear();
1975  block.emptyValue = emptyValue;
1976 }
1977 
1978 //----------------------------------------------------------------------------//
1979 
1981 
1982 //----------------------------------------------------------------------------//
1983 
1984 #endif // Include guard
SparseField::const_iterator::m_blockIsActivated
bool m_blockIsActivated
Used with delayed-load fields. Check if we've already activated the current blocks.
Definition: SparseField.h:1046
SparseField::const_iterator::setupNextBlock
void setupNextBlock(int i, int j, int k)
Definition: SparseField.h:998
FIELD3D_NAMESPACE_HEADER_CLOSE
#define FIELD3D_NAMESPACE_HEADER_CLOSE
Definition: ns.h:58
FieldBase
Definition: Field.h:91
BLOCK_ORDER
#define BLOCK_ORDER
Definition: SparseField.h:57
SparseFieldh
SparseField< half > SparseFieldh
Definition: SparseField.h:664
SparseField::m_blocks
Block * m_blocks
Array of blocks. Not using std::vector since SparseBlock is noncopyable.
Definition: SparseField.h:616
FieldRes::dataWindow
const Box3i & dataWindow() const
Returns the data window. Any coordinate inside this window is safe to pass to value() in the Field su...
Definition: Field.h:253
SparseField::sizeChanged
virtual void sizeChanged()
Subclasses should re-implement this if they need to perform memory allocations, etc....
Definition: SparseField.h:587
V3i
Imath::V3i V3i
Definition: SpiMathLib.h:71
SparseFile::Reference::layerPath
std::string layerPath
Definition: SparseFile.h:127
SparseField::FIELD3D_CLASSNAME_CLASSTYPE_IMPLEMENTATION
FIELD3D_CLASSNAME_CLASSTYPE_IMPLEMENTATION
Definition: SparseField.h:515
SparseField::iterator::y
int y
Definition: SparseField.h:1165
SparseField::setupReferenceBlocks
void setupReferenceBlocks()
Internal function to setup the Reference's block pointers, for use with dynamic reading.
Definition: SparseField.h:1413
SparseField::getBlockEmptyValue
const Data_T getBlockEmptyValue(int bi, int bj, int bk) const
Returns the constant value of an block, whether it's allocated already or not..
Definition: SparseField.h:1511
SparseField3d
SparseField< V3d > SparseField3d
Definition: SparseField.h:669
SparseField::iterator::m_blockOrder
int m_blockOrder
Block size.
Definition: SparseField.h:1197
V3d
Imath::V3d V3d
Definition: SpiMathLib.h:74
operator*
FIELD3D_VEC3_T< T > operator*(S s, const FIELD3D_VEC3_T< T > vec)
Scalar times Vec3 multiplication. Makes the interpolation calls cleaner.
Definition: FieldInterp.h:1558
SparseField::iterator
Definition: SparseField.h:1067
Sparse::SparseBlock::emptyValue
Data_T emptyValue
The value to use if the block isn't allocated. We allow setting this per block so that we for example...
Definition: SparseField.h:308
SparseField::iterator::m_window
Box3i m_window
Window to traverse.
Definition: SparseField.h:1201
LinearSparseFieldInterp::base
RefBase base
Convenience typedef for referring to base class.
Definition: SparseField.h:207
SparseField::releaseBlocks
int releaseBlocks(Functor_T func)
Releases any blocks that are deemed empty. This can be used to clean up after algorithms that write "...
Definition: SparseField.h:1551
Sparse::SparseBlock::value
Data_T & value(int i, int j, int k, int blockOrder)
Gets the value of a given voxel.
Definition: SparseField.h:249
SparseField::iterator::m_p
Data_T * m_p
Current pointed-to element.
Definition: SparseField.h:1191
SparseField::iterator::x
int x
Definition: SparseField.h:1165
Msg::SevWarning
Definition: Log.h:68
SparseField::begin
iterator begin()
Iterator to first element.
Definition: SparseField.h:1792
LinearSparseFieldInterp::ms_classType
static TemplatedFieldType< LinearSparseFieldInterp< Data_T > > ms_classType
Definition: SparseField.h:202
SparseField::setBlockEmptyValue
void setBlockEmptyValue(int bi, int bj, int bk, const Data_T &val)
Sets the constant value of an block. If the block is already allocated, it gets deallocated.
Definition: SparseField.h:1519
Sparse::SparseBlock
Definition: SparseField.h:227
SparseField::blockEnd
block_iterator blockEnd() const
Const iterator pointing to element one past the last valid block.
Definition: SparseField.h:1849
SparseField::iterator::m_blockStepsTicker
int m_blockStepsTicker
Ticker for how many more steps to take before resetting the pointer.
Definition: SparseField.h:1195
SparseField::iterator::setupNextBlock
void setupNextBlock(int i, int j, int k)
Convenience.
Definition: SparseField.h:1169
SparseField::iterator::m_field
class_type * m_field
Reference to field we're traversing.
Definition: SparseField.h:1203
SparseField::lvalue
virtual Data_T & lvalue(int i, int j, int k)
Write access to a voxel. The coordinates are global coordinates.
Definition: SparseField.h:1606
SparseField::const_iterator::m_blockStepsTicker
int m_blockStepsTicker
Ticker for how many more steps to take before resetting the pointer.
Definition: SparseField.h:1048
SparseField::class_type
SparseField< Data_T > class_type
Definition: SparseField.h:365
SparseField::clone
virtual FieldBase::Ptr clone() const
Returns a pointer to a copy of the field, pure virtual so ensure derived classes properly implement i...
Definition: SparseField.h:517
SparseFileManager::activateBlock
void activateBlock(int fileId, int blockIdx)
Called by SparseField when it's about to read from a block. This should not be called by the user,...
Definition: SparseFile.h:1256
FieldRes::m_dataWindow
Box3i m_dataWindow
Defines the area where data is allocated. This should be treated as a closed (i.e....
Definition: Field.h:310
SparseField::block_iterator::class_type
SparseField< Data_T > class_type
Convenience typedef.
Definition: SparseField.h:1217
SparseField::memSize
virtual long long int memSize() const
Returns the memory usage (in bytes)
Definition: SparseField.h:1708
SparseField::m_blockOrder
int m_blockOrder
Block order (size = 2^blockOrder)
Definition: SparseField.h:610
Field::value_type
Data_T value_type
Allows us to reference the template class.
Definition: Field.h:398
SparseField::numGrains
size_t numGrains() const
Number of 'grains' to use with threaded access.
Definition: SparseField.h:1943
SparseField::const_iterator::m_field
const class_type * m_field
Reference to field we're traversing.
Definition: SparseField.h:1056
SparseField::getVoxelInBlock
void getVoxelInBlock(int i, int j, int k, int &vi, int &vj, int &vk) const
Calculates the coordinates in a block for the given voxel index.
Definition: SparseField.h:1905
Sparse::SparseBlock::operator=
const SparseBlock & operator=(const SparseBlock &)
Non-copyable.
SparseField::blockIndexIsValid
bool blockIndexIsValid(int bi, int bj, int bk) const
Returns whether a block index is valid.
Definition: SparseField.h:1533
SparseField::cend
const_iterator cend() const
Const iterator pointing one element past the last valid one.
Definition: SparseField.h:1767
SparseField::block_iterator::x
int x
Current block index.
Definition: SparseField.h:1260
SparseField::SparseField
SparseField()
Constructs an empty buffer.
Definition: SparseField.h:1287
SparseField::const_iterator::z
int z
Definition: SparseField.h:988
Sparse::SparseBlock::~SparseBlock
~SparseBlock()
Dtor.
Definition: SparseField.h:239
SparseField::block_iterator::block_iterator
block_iterator(const class_type &field, const Box3i &window, const V3i &currentPos)
Constructor.
Definition: SparseField.h:1219
SparseField::const_iterator::m_blockK
int m_blockK
Definition: SparseField.h:1052
SparseField::value
virtual Data_T value(int i, int j, int k) const
Read access to a voxel. The coordinates are in integer voxel space .
Definition: SparseField.h:1598
V3f
Imath::V3f V3f
Definition: SpiMathLib.h:73
SparseField::block_iterator::recomputeBlockBoundingBox
void recomputeBlockBoundingBox()
Definition: SparseField.h:1262
FieldBase::name
std::string name
Optional name of the field.
Definition: Field.h:171
SparseField::m_blockXYSize
int m_blockXYSize
Block array res.x * res.y.
Definition: SparseField.h:614
Sparse::SparseBlock::SparseBlock
SparseBlock()
Ctor.
Definition: SparseField.h:232
SparseField::Ptr
boost::intrusive_ptr< SparseField > Ptr
Definition: SparseField.h:357
indexToCoord
V3i indexToCoord(const size_t idx, const V3i &res)
Definition: Field.h:1187
FieldBase::Ptr
boost::intrusive_ptr< FieldBase > Ptr
Definition: Field.h:97
LinearSparseFieldInterp::class_type
LinearSparseFieldInterp class_type
Definition: SparseField.h:97
SparseFile::Reference::blocks
BlockPtrs blocks
Pointers to each block. This is so we can go in and manipulate them as we please.
Definition: SparseFile.h:140
blockCoords
Box3i blockCoords(const Box3i &dvsBounds, const SparseField< Data_T > *f)
Definition: SparseField.h:676
SparseField::voxelIsInAllocatedBlock
bool voxelIsInAllocatedBlock(int i, int j, int k) const
Checks if a voxel is in an allocated block.
Definition: SparseField.h:1491
Sparse::CheckMaxAbs::check
bool check(const SparseBlock< Data_T > &block, Data_T &retEmptyValue, const V3i &validSize, const V3i &blockSize)
Checks whether a given block can be released. It's safe to assume that the block is allocated if this...
Definition: SparseField.h:825
SparseField
This Field subclass stores voxel data in block-allocated arrays.
Definition: SparseField.h:350
Sparse::SparseBlock::clear
void clear()
Remove data.
Definition: SparseField.h:273
SparseField::block_iterator::blockBoundingBox
const Box3i & blockBoundingBox()
Returns a reference to the bounding box representing the current block.
Definition: SparseField.h:1255
Sparse::SparseBlock::copy
void copy(const SparseBlock &other, size_t n)
Copy data from another block.
Definition: SparseField.h:285
detail::floor
FIELD3D_VEC3_T< T > floor(const FIELD3D_VEC3_T< T > &v)
Floor function for Vec3.
Definition: CoordSys.h:104
SparseField::addReference
void addReference(const std::string &filename, const std::string &layerPath, int valuesPerBlock, int numVoxels, int occupiedBlocks)
Internal function to create a Reference for the current field, for use in dynamic reading.
Definition: SparseField.h:1379
SparseField::getGrainBounds
bool getGrainBounds(const size_t idx, Box3i &vsBounds) const
Bounding box of the given 'grain'.
Definition: SparseField.h:1951
SparseField::const_iterator::const_iterator
const_iterator(const class_type &field, const Box3i &window, const V3i &currentPos, int blockOrder)
Definition: SparseField.h:898
SparseField::~SparseField
~SparseField()
Destructor.
Definition: SparseField.h:1311
SparseField::fastLValue
Data_T & fastLValue(int i, int j, int k)
Write access to voxel. Notice that this is non-virtual.
Definition: SparseField.h:1653
ns.h
SparseField::iterator::Block
Sparse::SparseBlock< Data_T > Block
Definition: SparseField.h:1167
SparseField::blockBegin
block_iterator blockBegin() const
Definition: SparseField.h:1837
SparseField::end
iterator end()
Iterator pointing one element past the last valid one.
Definition: SparseField.h:1814
continuousBounds
Box3d continuousBounds(const Box3i &bbox)
Definition: Field.h:1111
CubicGenericFieldInterp
Definition: DenseField.h:66
SparseField::const_iterator::m_blockOrder
int m_blockOrder
Block size.
Definition: SparseField.h:1050
Sparse::CheckAllEqual::check
bool check(const SparseBlock< Data_T > &block, Data_T &retEmptyValue, const V3i &validSize, const V3i &blockSize)
Checks whether a given block can be released. It's safe to assume that the block is allocated if this...
Definition: SparseField.h:720
SparseField::const_iterator::m_p
const Data_T * m_p
Current pointed-to element.
Definition: SparseField.h:1041
SparseField::setBlockOrder
void setBlockOrder(int order)
Sets the block order (i.e. the power-of-2 to use as block size.
Definition: SparseField.h:1466
SparseField::voxelCount
virtual size_t voxelCount() const
Counts the number of voxels. For most fields, this is just the volume of the data window,...
Definition: SparseField.h:1726
SparseField::copySparseField
void copySparseField(const SparseField &o)
Copies internal data, including blocks, from another SparseField, used by copy constructor and operat...
Definition: SparseField.h:1341
LinearSparseFieldInterp::sample
value_type sample(const SparseField< Data_T > &field, const V3d &vsP) const
Definition: SparseField.h:112
Sparse::CheckMaxAbs
Checks if all the absolute values in the SparseBlock are greater than some number....
Definition: SparseField.h:811
match
bool match(const std::string &name, const std::string &attribute, const std::vector< std::string > &patterns, const MatchFlags flags=MatchEmptyPattern)
Matches a <name>:<attribute> string against a set of patterns.
Definition: PatternMatch.cpp:102
detail::max
T max(const T a, const T2 b)
Max operation on mixed types.
Definition: FieldSampler.h:32
SparseField::const_iterator::m_manager
SparseFileManager * m_manager
Pointer to the singleton file manager.
Definition: SparseField.h:1058
SparseField::ms_classType
static TemplatedFieldType< SparseField< Data_T > > ms_classType
Definition: SparseField.h:633
SparseField::clear
virtual void clear(const Data_T &value)
Clears all the voxels in the storage.
Definition: SparseField.h:1452
SparseField::blockId
int blockId(int blockI, int blockJ, int blockK) const
Calculates the block number based on a block i,j,k index.
Definition: SparseField.h:1881
SparseFile::Reference::fileBlockIndices
std::vector< int > fileBlockIndices
Index in file for each block.
Definition: SparseFile.h:134
TemplatedFieldType::name
const char * name()
Definition: Traits.h:284
Sparse::CheckMaxAbs::CheckMaxAbs
CheckMaxAbs(Data_T maxValue)
Constructor. Takes max value.
Definition: SparseField.h:814
Sparse::SparseBlock::resize
void resize(int n)
Alloc data.
Definition: SparseField.h:259
SparseField::const_iterator::x
int x
Current x/y/z coord.
Definition: SparseField.h:988
SparseField::const_iterator::~const_iterator
~const_iterator()
Definition: SparseField.h:909
Sparse
Namespace for sparse field specifics.
Definition: SparseField.h:221
FieldRes::dataResolution
const V3i dataResolution() const
Definition: Field.h:256
SparseField::activateBlock
void activateBlock(const int blockId) const
Activates a given block.
Definition: SparseField.h:1927
SparseFileManager
Definition: SparseFile.h:396
SparseField::iterator::iterator
iterator(class_type &field, const Box3i &window, const V3i &currentPos, int blockOrder)
Definition: SparseField.h:1080
LinearSparseFieldInterp::staticClassName
static const char * staticClassName()
Definition: SparseField.h:100
SparseField3h
SparseField< V3h > SparseField3h
Definition: SparseField.h:667
Field.h
Contains Field, WritableField and ResizableField classes.
SparseField::staticClassName
static const char * staticClassName()
Definition: SparseField.h:368
SparseField::const_iterator::class_type
SparseField< Data_T > class_type
Definition: SparseField.h:897
detail::ceil
FIELD3D_VEC3_T< T > ceil(const FIELD3D_VEC3_T< T > &v)
Ceil function for Vec3.
Definition: CoordSys.h:114
SparseField::m_dummy
Data_T m_dummy
Dummy value used when needing to return but indicating a failed call.
Definition: SparseField.h:627
SparseField::iterator::class_type
SparseField< Data_T > class_type
Definition: SparseField.h:1079
FIELD3D_CLIP
#define FIELD3D_CLIP
Definition: SpiMathLib.h:90
SparseField::decBlockRef
void decBlockRef(const int blockId) const
Decrements the block ref count for the given block.
Definition: SparseField.h:1935
SparseFile.h
Contains functions controlling the loading of sparse fields.
SparseField::block_iterator::z
int z
Definition: SparseField.h:1260
Sparse::CheckMaxAbs::m_maxValue
Data_T m_maxValue
Definition: SparseField.h:872
SparseField::isDynamicLoad
bool isDynamicLoad() const
Whether the field is dynamically loaded.
Definition: SparseField.h:463
SparseFile::Reference
Definition: SparseFile.h:104
SparseField::block_iterator::m_currentBlockWindow
Box3i m_currentBlockWindow
Bounding box in voxel coordinates for the current block.
Definition: SparseField.h:1279
SparseField::block_iterator
Definition: SparseField.h:1213
SparseField::base
ResizableField< Data_T > base
Definition: SparseField.h:582
Sparse::SparseBlock::isAllocated
bool isAllocated
Whether the block is allocated or not.
Definition: SparseField.h:303
SparseField::iterator::m_isEmptyBlock
bool m_isEmptyBlock
Whether we're at an empty block and we don't increment m_p.
Definition: SparseField.h:1193
V3h
Imath::Vec3< half > V3h
Definition: SpiMathLib.h:72
SparseField::SparseFieldIO
friend class SparseFieldIO
Definition: SparseField.h:578
SparseFieldd
SparseField< double > SparseFieldd
Definition: SparseField.h:666
SparseField::block_iterator::y
int y
Definition: SparseField.h:1260
LinearSparseFieldInterp
Definition: SparseField.h:86
SparseField::block_iterator::m_window
Box3i m_window
Bounding box for block indices.
Definition: SparseField.h:1275
SparseField::const_iterator::Block
Sparse::SparseBlock< Data_T > Block
Definition: SparseField.h:994
SparseFile::Reference::occupiedBlocks
int occupiedBlocks
Definition: SparseFile.h:131
SparseField::const_iterator
Definition: SparseField.h:885
SparseField::getBlockCoord
void getBlockCoord(int i, int j, int k, int &bi, int &bj, int &bk) const
Calculates the block coordinates that a given set of voxel coords are in.
Definition: SparseField.h:1890
SparseFileManager::singleton
static SparseFileManager & singleton()
Returns a reference to the singleton instance.
Definition: SparseFile.cpp:66
SparseField::copyBlockStates
void copyBlockStates(const SparseField< Data_T > &o)
Internal function to copy empty values and allocated flags, without copying data, used when copying a...
Definition: SparseField.h:1399
LinearSparseFieldInterp::DEFINE_FIELD_RTTI_CONCRETE_CLASS
DEFINE_FIELD_RTTI_CONCRETE_CLASS
Definition: SparseField.h:98
SparseField::Block
Sparse::SparseBlock< Data_T > Block
Definition: SparseField.h:583
Sparse::CheckAllEqual
Checks if all the values in the SparseBlock are equal. Used by SparseField::releaseBlocks().
Definition: SparseField.h:710
ResizableField::sizeChanged
virtual void sizeChanged()
Subclasses should re-implement this if they need to perform memory allocations, etc....
Definition: Field.h:901
SparseField::incBlockRef
void incBlockRef(const int blockId) const
Increments the block ref count for the given block.
Definition: SparseField.h:1919
SparseField::blockData
Data_T * blockData(int bi, int bj, int bk) const
Returns a pointer to the data in a block, or null if the given block is unallocated.
Definition: SparseField.h:1694
SparseField::blockRes
V3i blockRes() const
Returns the resolution of the block array.
Definition: SparseField.h:1542
FIELD3D_CLASSTYPE_TEMPL_INSTANTIATION
FIELD3D_CLASSTYPE_TEMPL_INSTANTIATION(LinearSparseFieldInterp)
SparseField::fastValue
Data_T fastValue(int i, int j, int k) const
Read access to voxel. Notice that this is non-virtual.
Definition: SparseField.h:1614
SparseField::cbegin
const_iterator cbegin() const
Const iterator to first element. "cbegin" matches the tr1 c++ standard.
Definition: SparseField.h:1744
SparseFieldf
SparseField< float > SparseFieldf
Definition: SparseField.h:665
SparseField::LinearInterp
LinearSparseFieldInterp< Data_T > LinearInterp
Definition: SparseField.h:360
SparseField::iterator::m_blockK
int m_blockK
Definition: SparseField.h:1199
SparseField::deallocBlock
void deallocBlock(Block &block, const Data_T &emptyValue)
Deallocated the data of the given block and sets its empty value.
Definition: SparseField.h:1970
SparseField::blockOrder
int blockOrder() const
Returns the block order.
Definition: SparseField.h:1475
SparseField::setupBlocks
void setupBlocks()
Initializes the block structure. Will clear any existing data.
Definition: SparseField.h:1858
FIELD3D_NAMESPACE_OPEN
Definition: FieldMapping.cpp:74
LinearSparseFieldInterp::value_type
Data_T value_type
Definition: SparseField.h:92
Box3i
Imath::Box3i Box3i
Definition: SpiMathLib.h:77
LinearSparseFieldInterp::staticClassType
static const char * staticClassType()
Definition: SparseField.h:105
SparseField::Vec
std::vector< Ptr > Vec
Definition: SparseField.h:358
clipBounds
Box3i clipBounds(const Box3i &bbox, const Box3i &bounds)
Definition: Field.h:1145
SparseField::DEFINE_FIELD_RTTI_CONCRETE_CLASS
DEFINE_FIELD_RTTI_CONCRETE_CLASS
Definition: SparseField.h:366
Sparse::isAnyLess
bool isAnyLess(const Data_T &left, const Data_T &right)
Definition: SparseField.h:770
Sparse::SparseBlock::ms_resizeMutex
static boost::mutex ms_resizeMutex
Prevents concurrent allocation of blocks. There should be little contention, and this prevents multip...
Definition: SparseField.h:325
Msg::print
FIELD3D_API void print(Severity severity, const std::string &message)
Sends the string to the assigned output, prefixing the message with the severity.
Definition: Log.cpp:70
SparseField::m_blockRes
V3i m_blockRes
Block array resolution.
Definition: SparseField.h:612
LinearGenericFieldInterp
Definition: DenseField.h:64
TemplatedFieldType
Used to return a string for the name of a templated field.
Definition: Traits.h:282
RefBase
Definition: RefCount.h:106
SparseField::applyDataWindowOffset
void applyDataWindowOffset(int &i, int &j, int &k) const
Applies data window offset.
Definition: SparseField.h:455
detail::min
T min(const T a, const T2 b)
Min operation on mixed types.
Definition: FieldSampler.h:25
SparseField::m_fileId
int m_fileId
File id. Used with m_fileManager if active. Otherwise -1.
Definition: SparseField.h:624
SparseField::blockSize
int blockSize() const
Returns the block size.
Definition: SparseField.h:1483
SparseFile::Reference::numVoxels
int numVoxels
Definition: SparseFile.h:129
SparseField::block_iterator::m_field
const class_type & m_field
Pointer to field we're traversing.
Definition: SparseField.h:1277
SparseField::blockIsAllocated
bool blockIsAllocated(int bi, int bj, int bk) const
Checks if a block is allocated.
Definition: SparseField.h:1502
SparseField::staticClassType
static const char * staticClassType()
Definition: SparseField.h:373
ResizableField
Definition: Field.h:833
Sparse::SparseBlock::value
const Data_T & value(int i, int j, int k, int blockOrder) const
Gets the const value of a given voxel.
Definition: SparseField.h:255
SparseFile::Reference::filename
std::string filename
Definition: SparseFile.h:126
SparseField::m_numBlocks
size_t m_numBlocks
Number of blocks in field.
Definition: SparseField.h:618
LinearSparseFieldInterp::Ptr
boost::intrusive_ptr< LinearSparseFieldInterp > Ptr
Definition: SparseField.h:93
SparseField::m_fileManager
SparseFileManager * m_fileManager
Pointer to SparseFileManager. Used when doing dynamic reading. NULL if not in use.
Definition: SparseField.h:622
SparseField::CubicInterp
CubicGenericFieldInterp< SparseField< Data_T > > CubicInterp
Definition: SparseField.h:361
Sparse::SparseBlock::data
Data_T * data
Pointer to data. Null if block is unallocated.
Definition: SparseField.h:311
SparseField::operator=
SparseField & operator=(const SparseField &o)
Assignment operator. For cache-managed fields, it creates a new file reference, and for non-managed f...
Definition: SparseField.h:1328
SparseField3f
SparseField< V3f > SparseField3f
Definition: SparseField.h:668
SparseField::const_iterator::m_window
Box3i m_window
Window to traverse.
Definition: SparseField.h:1054
SparseField::iterator::z
int z
Definition: SparseField.h:1165
SparseField::const_iterator::m_isEmptyBlock
bool m_isEmptyBlock
Whether we're at an empty block and we don't increment m_p.
Definition: SparseField.h:1043
SparseFile::Reference::valuesPerBlock
int valuesPerBlock
Definition: SparseFile.h:128