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/lexical_cast.hpp>
52 
53 #include "Field.h"
54 #include "SparseFile.h"
55 
56 #define BLOCK_ORDER 4 // 2^BLOCK_ORDER is the block size along each axis
57 
58 //----------------------------------------------------------------------------//
59 
60 #include "ns.h"
61 
63 
64 //----------------------------------------------------------------------------//
65 // Forward declarations
66 //----------------------------------------------------------------------------//
67 
68 template <class Field_T>
70 template <class Field_T>
72 
73 //----------------------------------------------------------------------------//
74 // SparseBlock
75 //----------------------------------------------------------------------------//
76 
79 namespace Sparse {
80 
84 template <typename Data_T>
85 struct SparseBlock
86 {
87  // Constructors --------------------------------------------------------------
88 
91  : isAllocated(false),
92  emptyValue(static_cast<Data_T>(0))
93  { /* Empty */ }
94 
95  // Main methods --------------------------------------------------------------
96 
98  Data_T& value(int i, int j, int k, int blockOrder)
100  { return data[(k << blockOrder << blockOrder) + (j << blockOrder) + i]; }
101 
104  const Data_T& value(int i, int j, int k, int blockOrder) const
105  { return data[(k << blockOrder << blockOrder) + (j << blockOrder) + i]; }
106 
108  void resize(int n)
109  { this->data.resize(n); }
110 
112  void clear()
113  { std::vector<Data_T>().swap(data); }
114 
116  Data_T& dataRef()
117  { return data[0]; }
118 
119  // Data members --------------------------------------------------------------
120 
123 
127  Data_T emptyValue;
128 
130  std::vector<Data_T> data;
131 
132 private:
133 
136 
137 };
138 
139 } // namespace Sparse
140 
141 //----------------------------------------------------------------------------//
142 // SparseField
143 //----------------------------------------------------------------------------//
144 
157 //----------------------------------------------------------------------------//
158 
159 template <class Data_T>
161  : public ResizableField<Data_T>
162 {
163 public:
164 
165  // Typedefs ------------------------------------------------------------------
166 
167  typedef boost::intrusive_ptr<SparseField> Ptr;
168  typedef std::vector<Ptr> Vec;
169 
172 
173  // RTTI replacement ----------------------------------------------------------
174 
177 
178  static const char *staticClassName()
179  {
180  return "SparseField";
181  }
182 
183  static const char *classType()
184  {
186  }
187 
188  // Constructors --------------------------------------------------------------
189 
192 
194  SparseField();
195 
197  SparseField(const SparseField &o);
198 
200  ~SparseField();
201 
204  SparseField& operator=(const SparseField &o);
205 
206  // \}
207 
208  // Main methods --------------------------------------------------------------
209 
211  virtual void clear(const Data_T &value);
212 
215  void setBlockOrder(int order);
216 
218  int blockOrder() const;
219 
221  int blockSize() const;
222 
224  bool voxelIsInAllocatedBlock(int i, int j, int k) const;
225 
227  bool blockIsAllocated(int bi, int bj, int bk) const;
228 
231  const Data_T getBlockEmptyValue(int bi, int bj, int bk) const;
232 
235  void setBlockEmptyValue(int bi, int bj, int bk, const Data_T &val);
236 
238  bool blockIndexIsValid(int bi, int bj, int bk) const;
239 
241  V3i blockRes() const;
242 
248  template <typename Functor_T>
249  int releaseBlocks(Functor_T func);
250 
252  int blockId(int blockI, int blockJ, int blockK) const;
253 
257  void getBlockCoord(int i, int j, int k, int &bi, int &bj, int &bk) const;
258 
262  void getVoxelInBlock(int i, int j, int k, int &vi, int &vj, int &vk) const;
263 
265  void applyDataWindowOffset(int &i, int &j, int &k) const
266  {
267  i -= base::m_dataWindow.min.x;
268  j -= base::m_dataWindow.min.y;
269  k -= base::m_dataWindow.min.z;
270  }
271 
272  // From Field base class -----------------------------------------------------
273 
276  virtual Data_T value(int i, int j, int k) const;
277  virtual long long int memSize() const;
279 
280  // From WritableField base class ---------------------------------------------
281 
284  virtual Data_T& lvalue(int i, int j, int k);
286 
287  // Concrete voxel access -----------------------------------------------------
288 
290  Data_T fastValue(int i, int j, int k) const;
292  Data_T& fastLValue(int i, int j, int k);
293 
294  // From FieldBase ------------------------------------------------------------
295 
298  virtual std::string className() const
299  { return staticClassName(); }
300 
301  virtual FieldBase::Ptr clone() const
302  { return Ptr(new SparseField(*this)); }
303 
305 
306  // Iterators -----------------------------------------------------------------
307 
310 
312  class const_iterator;
313 
315  const_iterator cbegin() const;
317  const_iterator cbegin(const Box3i &subset) const;
319  const_iterator cend() const;
322  const_iterator cend(const Box3i &subset) const;
323 
327  class iterator;
328 
330  iterator begin();
332  iterator begin(const Box3i &subset);
334  iterator end();
337  iterator end(const Box3i &subset);
338 
342  class block_iterator;
343 
344  block_iterator blockBegin() const;
346  block_iterator blockEnd() const;
347 
349 
350  // Internal utility functions ------------------------------------------------
351 
354  void addReference(const std::string &filename, const std::string &layerPath,
355  int valuesPerBlock, int occupiedBlocks);
358  void setupReferenceBlocks();
359 
360  protected:
361 
362  friend class SparseFieldIO;
363 
364  // Typedefs ------------------------------------------------------------------
365 
368 
369  // From ResizableField class -------------------------------------------------
370 
371  virtual void sizeChanged()
372  {
373  // Call base class
375  setupBlocks();
376  }
377 
378  // Convenience methods -------------------------------------------------------
379 
382 
384  void setupBlocks();
385 
387  void deallocBlock(Block &block, const Data_T &emptyValue);
388 
390 
391  // Data members --------------------------------------------------------------
392 
400  std::vector<Block> m_blocks;
401 
406  int m_fileId;
407 
409  Data_T m_dummy;
410 
411 private:
412 
413  // Static data members -------------------------------------------------------
414 
416 
417  // Utility methods -----------------------------------------------------------
418 
421  void copySparseField(const SparseField &o);
422 
425  void copyBlockStates(const SparseField<Data_T> &o);
426 
427 };
428 
429 //----------------------------------------------------------------------------//
430 // Static member instantiations
431 //----------------------------------------------------------------------------//
432 
434 
435 //----------------------------------------------------------------------------//
436 // Typedefs
437 //----------------------------------------------------------------------------//
438 
445 
446 //----------------------------------------------------------------------------//
447 // Helper functors
448 //----------------------------------------------------------------------------//
449 
450 namespace Sparse {
451 
454 template <typename Data_T>
456 {
465  bool check(const SparseBlock<Data_T> &block, Data_T &retEmptyValue,
466  const V3i &validSize, const V3i &blockSize)
467  {
468  // Store first value
469  Data_T first = block.data[0];
470  // Iterate over rest
471  bool match = true;
472  if (validSize == blockSize) {
473  // interior block so look at all voxels
474  for (typename std::vector<Data_T>::const_iterator i = block.data.begin();
475  i != block.data.end(); ++i) {
476  if (*i != first) {
477  match = false;
478  break;
479  }
480  }
481  } else {
482  // only look at valid voxels
483  int x=0, y=0, z=0;
484  for (typename std::vector<Data_T>::const_iterator i = block.data.begin();
485  i != block.data.end(); ++i, ++x) {
486  if (x >= blockSize.x) {
487  x = 0;
488  ++y;
489  if (y >= blockSize.y) {
490  y = 0;
491  ++z;
492  }
493  }
494  if (x >= validSize.x || y >= validSize.y || z >= validSize.z) {
495  continue;
496  }
497 
498  if (*i != first) {
499  match = false;
500  break;
501  }
502  }
503  } // end of interior block test
504 
505  if (match) {
506  retEmptyValue = first;
507  return true;
508  } else {
509  return false;
510  }
511  }
512 };
513 
514 //----------------------------------------------------------------------------//
515 
516 template <typename Data_T>
517 inline bool isAnyLess(const Data_T &left, const Data_T &right)
518 {
519  return (std::abs(left) < right);
520 }
521 
522 //----------------------------------------------------------------------------//
523 
524 template <>
525 inline bool isAnyLess(const V3h &left, const V3h &right)
526 {
527  return (std::abs(left.x) < right.x ||
528  std::abs(left.y) < right.y ||
529  std::abs(left.z) < right.z );
530 }
531 
532 //----------------------------------------------------------------------------//
533 
534 template <>
535 inline bool isAnyLess(const V3f &left, const V3f &right)
536 {
537  return (std::abs(left.x) < right.x ||
538  std::abs(left.y) < right.y ||
539  std::abs(left.z) < right.z );
540 }
541 
542 //----------------------------------------------------------------------------//
543 
544 template <>
545 inline bool isAnyLess(const V3d &left, const V3d &right)
546 {
547  return (std::abs(left.x) < right.x ||
548  std::abs(left.y) < right.y ||
549  std::abs(left.z) < right.z );
550 }
551 
552 //----------------------------------------------------------------------------//
553 
557 template <typename Data_T>
559 {
561  CheckMaxAbs(Data_T maxValue)
562  : m_maxValue(maxValue)
563  { }
572  bool check(const SparseBlock<Data_T> &block, Data_T &retEmptyValue,
573  const V3i &validSize, const V3i &blockSize)
574  {
575  // Store first value
576  Data_T first = block.data[0];
577  // Iterate over rest
578  bool allGreater = true;
579  if (validSize == blockSize) {
580  // interior block so look at all voxels
581  for (typename std::vector<Data_T>::const_iterator i = block.data.begin();
582  i != block.data.end(); ++i) {
583  if (isAnyLess<Data_T>(*i, m_maxValue)) {
584  allGreater = false;
585  break;
586  }
587  }
588  } else {
589  // only look at valid voxels
590  int x=0, y=0, z=0;
591  for (typename std::vector<Data_T>::const_iterator i = block.data.begin();
592  i != block.data.end(); ++i, ++x) {
593  if (x >= blockSize.x) {
594  x = 0;
595  ++y;
596  if (y >= blockSize.y) {
597  y = 0;
598  ++z;
599  }
600  }
601  if (x >= validSize.x || y >= validSize.y || z >= validSize.z) {
602  continue;
603  }
604  if (isAnyLess<Data_T>(*i, m_maxValue)) {
605  allGreater = false;
606  break;
607  }
608  }
609  } // end of interior block test
610 
611  if (allGreater) {
612  retEmptyValue = first;
613  return true;
614  } else {
615  return false;
616  }
617  }
618 private:
619  Data_T m_maxValue;
620 };
621 
622 } // namespace Sparse
623 
624 //----------------------------------------------------------------------------//
625 // SparseField::const_iterator
626 //----------------------------------------------------------------------------//
627 
629 template <class Data_T>
631 {
632  public:
634  const_iterator(const class_type &field,
635  const Box3i &window,
636  const V3i &currentPos, int blockOrder)
637  : x(currentPos.x), y(currentPos.y), z(currentPos.z),
638  m_p(NULL), m_blockIsActivated(false),
639  m_blockStepsTicker(0), m_blockOrder(blockOrder),
640  m_blockId(-1), m_window(window), m_field(&field)
641  {
642  m_manager = m_field->m_fileManager;
643  setupNextBlock(x, y, z);
644  }
646  if (m_manager && m_blockId >= 0 &&
647  m_blockId < static_cast<int>(m_field->m_blocks.size())) {
648  if (m_field->m_blocks[m_blockId].isAllocated)
649  m_manager->decBlockRef<Data_T>(m_field->m_fileId, m_blockId);
650  }
651  }
652  const const_iterator& operator ++ ()
653  {
654  bool resetPtr = false;
655  // Check against end of data window
656  if (x == m_window.max.x) {
657  if (y == m_window.max.y) {
658  x = m_window.min.x;
659  y = m_window.min.y;
660  ++z;
661  resetPtr = true;
662  } else {
663  x = m_window.min.x;
664  ++y;
665  resetPtr = true;
666  }
667  } else {
668  ++x;
669  }
670  // These can both safely be incremented here
671  ++m_blockStepsTicker;
672  // ... but only step forward if we're in a non-empty block
673  if (!m_isEmptyBlock && (!m_manager || m_blockIsActivated))
674  ++m_p;
675  // Check if we've reached the end of this block
676  if (m_blockStepsTicker == (1 << m_blockOrder))
677  resetPtr = true;
678  if (resetPtr) {
679  // If we have, we need to reset the current block, etc.
680  m_blockStepsTicker = 0;
681  setupNextBlock(x, y, z);
682  }
683  return *this;
684  }
685  template <class Iter_T>
686  inline bool operator == (const Iter_T &rhs) const
687  {
688  return x == rhs.x && y == rhs.y && z == rhs.z;
689  }
690  template <class Iter_T>
691  inline bool operator != (const Iter_T &rhs) const
692  {
693  return x != rhs.x || y != rhs.y || z != rhs.z;
694  }
695  inline const Data_T& operator * () const
696  {
697  if (!m_isEmptyBlock && m_manager && !m_blockIsActivated) {
698  m_manager->activateBlock<Data_T>(m_field->m_fileId, m_blockId);
699  m_blockIsActivated = true;
700  const Block &block = m_field->m_blocks[m_blockId];
701  int vi, vj, vk;
702  m_field->getVoxelInBlock(x, y, z, vi, vj, vk);
703  m_p = &block.value(vi, vj, vk, m_blockOrder);
704  }
705  return *m_p;
706  }
707  inline const Data_T* operator -> () const
708  {
709  if (!m_isEmptyBlock && m_manager && !m_blockIsActivated) {
710  SparseFileManager *manager = m_field->m_fileManager;
711  manager->activateBlock<Data_T>(m_field->m_fileId, m_blockId);
712  m_blockIsActivated = true;
713  const Block &block = m_field->m_blocks[m_blockId];
714  int vi, vj, vk;
715  m_field->getVoxelInBlock(x, y, z, vi, vj, vk);
716  m_p = &block.value(vi, vj, vk, m_blockOrder);
717  }
718  return m_p;
719  }
720 
721  // Public data members -------------------------------------------------------
722 
724  int x, y, z;
725 
726 private:
727 
728  // Typedefs ------------------------------------------------------------------
729 
731 
732  // Convenience methods -------------------------------------------------------
733 
734  void setupNextBlock(int i, int j, int k)
735  {
736  m_field->applyDataWindowOffset(i, j, k);
737  m_field->getBlockCoord(i, j, k, m_blockI, m_blockJ, m_blockK);
738  int oldBlockId = m_blockId;
739  m_blockId = m_field->blockId(m_blockI, m_blockJ, m_blockK);
740  if (m_manager && oldBlockId != m_blockId &&
741  oldBlockId >= 0 &&
742  oldBlockId < static_cast<int>(m_field->m_blocks.size()) &&
743  m_field->m_blocks[oldBlockId].isAllocated) {
744  m_manager->decBlockRef<Data_T>(m_field->m_fileId, oldBlockId);
745  }
746  if (m_blockId >= m_field->m_blockXYSize * m_field->m_blockRes.z) {
747  m_isEmptyBlock = true;
748  return;
749  }
750 
751  const Block &block = m_field->m_blocks[m_blockId];
752  int vi, vj, vk;
753  m_field->getVoxelInBlock(i, j, k, vi, vj, vk);
754  m_blockStepsTicker = vi;
755  if (block.isAllocated) {
756  if (m_manager && oldBlockId != m_blockId && m_blockId >= 0) {
757  m_manager->incBlockRef<Data_T>(m_field->m_fileId, m_blockId);
758  // this is a managed field, so the block may not be loaded
759  // yet, so don't bother setting m_p yet (it'll get set in the
760  // * and -> operators when the block is activated)
761  } else {
762  // only set m_p to the voxel's address if this is not a
763  // managed field, i.e., if the data is already in memory.
764  m_p = &block.value(vi, vj, vk, m_blockOrder);
765  }
766  m_isEmptyBlock = false;
767  } else {
768  m_p = &block.emptyValue;
769  m_isEmptyBlock = true;
770  }
771  if (m_field->m_fileManager) {
772  m_blockIsActivated = false;
773  }
774  }
775 
777  mutable const Data_T *m_p;
782  mutable bool m_blockIsActivated;
788  int m_blockI, m_blockJ, m_blockK, m_blockId;
792  const class_type *m_field;
795 };
796 
797 //----------------------------------------------------------------------------//
798 // SparseField::iterator
799 //----------------------------------------------------------------------------/
800 
802 template <class Data_T>
803 class SparseField<Data_T>::iterator
804 {
805  public:
807  iterator(class_type &field,
808  const Box3i &window,
809  const V3i &currentPos, int blockOrder)
810  : x(currentPos.x), y(currentPos.y), z(currentPos.z),
811  m_p(NULL), m_blockStepsTicker(0), m_blockOrder(blockOrder),
812  m_blockId(-1), m_window(window), m_field(&field)
813  {
814  setupNextBlock(x, y, z);
815  }
816  const iterator& operator ++ ()
817  {
818  bool resetPtr = false;
819  // Check against end of data window
820  if (x == m_window.max.x) {
821  if (y == m_window.max.y) {
822  x = m_window.min.x;
823  y = m_window.min.y;
824  ++z;
825  resetPtr = true;
826  } else {
827  x = m_window.min.x;
828  ++y;
829  resetPtr = true;
830  }
831  } else {
832  ++x;
833  }
834  // These can both safely be incremented here
835  ++m_blockStepsTicker;
836  // ... but only step forward if we're in a non-empty block
837  if (!m_isEmptyBlock)
838  ++m_p;
839  // Check if we've reached the end of this block
840  if (m_blockStepsTicker == (1 << m_blockOrder))
841  resetPtr = true;
842  if (resetPtr) {
843  // If we have, we need to reset the current block, etc.
844  m_blockStepsTicker = 0;
845  setupNextBlock(x, y, z);
846  }
847  return *this;
848  }
849  inline bool operator == (const iterator &rhs) const
850  {
851  return x == rhs.x && y == rhs.y && z == rhs.z;
852  }
853  inline bool operator != (const iterator &rhs) const
854  {
855  return x != rhs.x || y != rhs.y || z != rhs.z;
856  }
857  inline Data_T& operator * ()
858  {
859  if (m_field->m_fileManager) {
860  assert(false && "Dereferencing iterator on a dynamic-read sparse field");
861  Msg::print(Msg::SevWarning, "Dereferencing iterator on a dynamic-read "
862  "sparse field");
863  return *m_p;
864  }
865  // If the block is currently empty, we must allocate it
866  if (m_isEmptyBlock) {
867  // Touch the voxel to allocate the block
868  m_field->lvalue(x, y, z);
869  // Set up the block again
870  setupNextBlock(x, y, z);
871  }
872  return *m_p;
873  }
874  inline Data_T* operator -> ()
875  {
876  if (m_field->m_fileManager) {
877  assert(false && "Dereferencing iterator on a dynamic-read sparse field");
878  Msg::print(Msg::SevWarning, "Dereferencing iterator on a dynamic-read "
879  "sparse field");
880  return m_p;
881  }
882  // If the block is currently empty, we must allocate it
883  if (m_isEmptyBlock) {
884  // Touch the voxel to allocate the block
885  m_field->lvalue(x, y, z);
886  // Set up the block again
887  setupNextBlock(x, y, z);
888  }
889  return m_p;
890  }
891  // Public data members
892  int x, y, z;
893 private:
896  void setupNextBlock(int i, int j, int k)
897  {
898  m_field->applyDataWindowOffset(i, j, k);
899  m_field->getBlockCoord(i, j, k, m_blockI, m_blockJ, m_blockK);
900  m_blockId = m_field->blockId(m_blockI, m_blockJ, m_blockK);
901  if (m_blockId >= m_field->m_blockXYSize * m_field->m_blockRes.z) {
902  m_isEmptyBlock = true;
903  return;
904  }
905  Block &block = m_field->m_blocks[m_blockId];
906  int vi, vj, vk;
907  m_field->getVoxelInBlock(i, j, k, vi, vj, vk);
908  m_blockStepsTicker = vi;
909  if (block.isAllocated) {
910  m_p = &block.value(vi, vj, vk, m_blockOrder);
911  m_isEmptyBlock = false;
912  } else {
913  m_p = &block.emptyValue;
914  m_isEmptyBlock = true;
915  }
916  }
918  Data_T *m_p;
926  int m_blockI, m_blockJ, m_blockK, m_blockId;
930  class_type *m_field;
931 };
932 
933 //----------------------------------------------------------------------------//
934 // SparseField::block_iterator
935 //----------------------------------------------------------------------------/
936 
939 template <class Data_T>
941 {
942  public:
946  block_iterator(const class_type &field, const Box3i &window,
947  const V3i &currentPos)
948  : x(currentPos.x), y(currentPos.y), z(currentPos.z),
949  m_window(window), m_field(field)
950  {
951  recomputeBlockBoundingBox();
952  }
954  const block_iterator& operator ++ ()
955  {
956  if (x == m_window.max.x) {
957  if (y == m_window.max.y) {
958  x = m_window.min.x;
959  y = m_window.min.y;
960  ++z;
961  } else {
962  x = m_window.min.x;
963  ++y;
964  }
965  } else {
966  ++x;
967  }
968  recomputeBlockBoundingBox();
969  return *this;
970  }
972  inline bool operator == (const block_iterator &rhs) const
973  {
974  return x == rhs.x && y == rhs.y && z == rhs.z;
975  }
977  inline bool operator != (const block_iterator &rhs) const
978  {
979  return x != rhs.x || y != rhs.y || z != rhs.z;
980  }
983  {
984  return m_currentBlockWindow;
985  }
987  int x, y, z;
988 private:
990  {
991  Box3i box;
992  int blockSize = m_field.blockSize();
993  box.min = V3i(x * blockSize, y * blockSize, z * blockSize);
994  box.max = box.min + V3i(blockSize - 1, blockSize - 1, blockSize - 1);
995  // Clamp the box
996  box.min = FIELD3D_CLIP(box.min, m_field.dataWindow());
997  box.max = FIELD3D_CLIP(box.max, m_field.dataWindow());
998  // Set the member variable
999  m_currentBlockWindow = box;
1000  }
1004  const class_type& m_field;
1007 };
1008 
1009 //----------------------------------------------------------------------------//
1010 // SparseField implementations
1011 //----------------------------------------------------------------------------//
1012 
1013 template <class Data_T>
1015  : base(),
1016  m_blockOrder(BLOCK_ORDER),
1017  m_fileManager(NULL)
1018 {
1019  setupBlocks();
1020 }
1021 
1022 //----------------------------------------------------------------------------//
1023 
1024 template <class Data_T>
1026  base(o)
1027 {
1028  copySparseField(o);
1029 }
1030 
1031 //----------------------------------------------------------------------------//
1032 
1033 template <class Data_T>
1035 {
1036  if (m_fileManager) {
1037  // this file is dynamically managed, so we need to ensure the
1038  // cache doesn't point to this field's blocks because they are
1039  // about to be deleted
1040  m_fileManager->removeFieldFromCache<Data_T>(m_fileId);
1041  }
1042 }
1043 
1044 //----------------------------------------------------------------------------//
1045 
1046 template <class Data_T>
1049 {
1050  if (this != &o) {
1051  this->base::operator=(o);
1052  copySparseField(o);
1053  }
1054  return *this;
1055 }
1056 
1057 //----------------------------------------------------------------------------//
1058 
1059 template <class Data_T>
1060 void
1062 {
1063  m_blockOrder = o.m_blockOrder;
1064  if (o.m_fileManager) {
1065  // allocate m_blocks, sets m_blockRes, m_blockXYSize, m_blocks
1066  setupBlocks();
1067 
1068  m_fileManager = o.m_fileManager;
1069  SparseFile::Reference<Data_T> &oldReference =
1070  m_fileManager->reference<Data_T>(o.m_fileId);
1071  addReference(oldReference.filename, oldReference.layerPath,
1072  oldReference.valuesPerBlock,
1073  oldReference.occupiedBlocks);
1074  copyBlockStates(o);
1075  setupReferenceBlocks();
1076  } else {
1077  // directly copy all values and blocks from the source, no extra setup
1078  m_blockRes = o.m_blockRes;
1079  m_blockXYSize = o.m_blockXYSize;
1080  m_blocks = o.m_blocks;
1081  m_fileId = -1;
1082  m_fileManager = NULL;
1083  }
1084 }
1085 
1086 //----------------------------------------------------------------------------//
1087 
1088 template <class Data_T>
1089 void SparseField<Data_T>::addReference(const std::string &filename,
1090  const std::string &layerPath,
1091  int valuesPerBlock,
1092  int occupiedBlocks)
1093 {
1094  m_fileManager = &SparseFileManager::singleton();
1095  m_fileId = m_fileManager->getNextId<Data_T>(filename, layerPath);
1096  // Set up the manager data
1097  SparseFile::Reference<Data_T> &reference =
1098  m_fileManager->reference<Data_T>(m_fileId);
1099  reference.valuesPerBlock = valuesPerBlock;
1100  reference.occupiedBlocks = occupiedBlocks;
1101  reference.setNumBlocks(m_blocks.size());
1102 }
1103 
1104 //----------------------------------------------------------------------------//
1105 
1106 template <class Data_T>
1108 {
1109  if (m_blocks.size() != o.m_blocks.size()) return;
1110 
1111  typename std::vector<Sparse::SparseBlock<Data_T> >::iterator b =
1112  m_blocks.begin();
1113  typename std::vector<Sparse::SparseBlock<Data_T> >::iterator bend =
1114  m_blocks.end();
1115  typename std::vector<Sparse::SparseBlock<Data_T> >::const_iterator ob =
1116  o.m_blocks.begin();
1117 
1118  for (; b != bend; ++b, ++ob) {
1119  b->isAllocated = ob->isAllocated;
1120  b->emptyValue = ob->emptyValue;
1121  b->clear();
1122  }
1123 }
1124 
1125 //----------------------------------------------------------------------------//
1126 
1127 template <class Data_T>
1129 {
1130  if (!m_fileManager || m_fileId < 0) return;
1131 
1132  SparseFile::Reference<Data_T> &reference =
1133  m_fileManager->reference<Data_T>(m_fileId);
1134 
1135  std::vector<int>::iterator fb = reference.fileBlockIndices.begin();
1137  reference.blocks.begin();
1138  typename std::vector<Sparse::SparseBlock<Data_T> >::iterator b =
1139  m_blocks.begin();
1140  typename std::vector<Sparse::SparseBlock<Data_T> >::iterator bend =
1141  m_blocks.end();
1142  int nextBlockIdx = 0;
1143 
1144  for (; b != bend; ++b, ++fb, ++bp) {
1145  if (b->isAllocated) {
1146  *fb = nextBlockIdx;
1147  *bp = &(*b);
1148  nextBlockIdx++;
1149  } else {
1150  *fb = -1;
1151  }
1152  }
1153 }
1154 
1155 //----------------------------------------------------------------------------//
1156 
1157 template <class Data_T>
1158 void SparseField<Data_T>::clear(const Data_T &value)
1159 {
1160  // If we're clearing, we can get rid of all current blocks
1161  setupBlocks();
1162  // Then just fill in the default values
1163  typename std::vector<Block>::iterator i;
1164  typename std::vector<Block>::iterator end;
1165  for (i = m_blocks.begin(), end = m_blocks.end(); i != end; ++i) {
1166  i->emptyValue = value;
1167  }
1168 }
1169 
1170 //----------------------------------------------------------------------------//
1171 
1172 template <class Data_T>
1174 {
1175  m_blockOrder = order;
1176  setupBlocks();
1177 }
1178 
1179 //----------------------------------------------------------------------------//
1180 
1181 template <class Data_T>
1183 {
1184  return m_blockOrder;
1185 }
1186 
1187 //----------------------------------------------------------------------------//
1188 
1189 template <class Data_T>
1191 {
1192  return 1 << m_blockOrder;
1193 }
1194 
1195 //----------------------------------------------------------------------------//
1196 
1197 template <class Data_T>
1198 bool SparseField<Data_T>::voxelIsInAllocatedBlock(int i, int j, int k) const
1199 {
1200  int bi, bj, bk;
1201  applyDataWindowOffset(i, j, k);
1202  getBlockCoord(i, j, k, bi, bj, bk);
1203  return blockIsAllocated(bi, bj, bk);
1204 }
1205 
1206 //----------------------------------------------------------------------------//
1207 
1208 template <class Data_T>
1209 bool SparseField<Data_T>::blockIsAllocated(int bi, int bj, int bk) const
1210 {
1211  const Block &block = m_blocks[blockId(bi, bj, bk)];
1212  return block.isAllocated;
1213 }
1214 
1215 //----------------------------------------------------------------------------//
1216 
1217 template <class Data_T>
1218 const Data_T SparseField<Data_T>::getBlockEmptyValue(int bi, int bj, int bk) const
1219 {
1220  return m_blocks[blockId(bi, bj, bk)].emptyValue;
1221 }
1222 
1223 //----------------------------------------------------------------------------//
1224 
1225 template <class Data_T>
1226 void SparseField<Data_T>::setBlockEmptyValue(int bi, int bj, int bk,
1227  const Data_T &val)
1228 {
1229  Block &block = m_blocks[blockId(bi, bj, bk)];
1230  if (block.isAllocated) {
1231  deallocBlock(block, val);
1232  } else {
1233  block.emptyValue = val;
1234  }
1235 }
1236 
1237 //----------------------------------------------------------------------------//
1238 
1239 template <class Data_T>
1240 bool SparseField<Data_T>::blockIndexIsValid(int bi, int bj, int bk) const
1241 {
1242  return bi >= 0 && bj >= 0 && bk >= 0 &&
1243  bi < m_blockRes.x && bj < m_blockRes.y && bk < m_blockRes.z;
1244 }
1245 
1246 //----------------------------------------------------------------------------//
1247 
1248 template <class Data_T>
1250 {
1251  return m_blockRes;
1252 }
1253 
1254 //----------------------------------------------------------------------------//
1255 
1256 template <class Data_T>
1257 template <typename Functor_T>
1259 {
1260  Data_T emptyValue;
1261  int numDeallocs = 0;
1262  typename std::vector<Block>::iterator i;
1263 
1264  // If the block is on the edge of the field, it may have unused
1265  // voxels, with undefined values. We need to pass the range of
1266  // valid voxels into the check function, so it only looks at valid
1267  // voxels.
1268  V3i dataRes = FieldRes::dataResolution();
1269  V3i validSize;
1270  V3i blockAllocSize(blockSize());
1271  int bx, by, bz;
1272 
1273  for (i = m_blocks.begin(), bx=0, by=0, bz=0; i != m_blocks.end(); ++i, ++bx) {
1274  if (bx >= m_blockRes.x) {
1275  bx = 0;
1276  ++by;
1277  if (by >= m_blockRes.y) {
1278  by = 0;
1279  ++bz;
1280  }
1281  }
1282  validSize = blockAllocSize;
1283  if (bx == m_blockRes.x-1) {
1284  validSize.x = dataRes.x - bx * blockAllocSize.x;
1285  }
1286  if (by == m_blockRes.y-1) {
1287  validSize.y = dataRes.y - by * blockAllocSize.y;
1288  }
1289  if (bz == m_blockRes.z-1) {
1290  validSize.z = dataRes.z - bz * blockAllocSize.z;
1291  }
1292 
1293  if (i->isAllocated) {
1294  if (func.check(*i, emptyValue, validSize, blockAllocSize)) {
1295  deallocBlock(*i, emptyValue);
1296  numDeallocs++;
1297  }
1298  }
1299  }
1300  return numDeallocs;
1301 }
1302 
1303 //----------------------------------------------------------------------------//
1304 
1305 template <class Data_T>
1306 Data_T SparseField<Data_T>::value(int i, int j, int k) const
1307 {
1308  return fastValue(i, j, k);
1309 }
1310 
1311 //----------------------------------------------------------------------------//
1312 
1313 template <class Data_T>
1314 Data_T& SparseField<Data_T>::lvalue(int i, int j, int k)
1315 {
1316  return fastLValue(i, j, k);
1317 }
1318 
1319 //----------------------------------------------------------------------------//
1320 
1321 template <class Data_T>
1322 Data_T SparseField<Data_T>::fastValue(int i, int j, int k) const
1323 {
1324  assert (i >= base::m_dataWindow.min.x);
1325  assert (i <= base::m_dataWindow.max.x);
1326  assert (j >= base::m_dataWindow.min.y);
1327  assert (j <= base::m_dataWindow.max.y);
1328  assert (k >= base::m_dataWindow.min.z);
1329  assert (k <= base::m_dataWindow.max.z);
1330  // Add crop window offset
1331  applyDataWindowOffset(i, j, k);
1332  // Find block coord
1333  int bi, bj, bk;
1334  getBlockCoord(i, j, k, bi, bj, bk);
1335  // Find coord in block
1336  int vi, vj, vk;
1337  getVoxelInBlock(i, j, k, vi, vj, vk);
1338  // Get the actual block
1339  int id = blockId(bi, bj, bk);
1340 
1341  const Block &block = m_blocks[id];
1342  // Check if block data is allocated
1343  if (block.isAllocated) {
1344  if (m_fileManager) {
1345  m_fileManager->incBlockRef<Data_T>(m_fileId, id);
1346  m_fileManager->activateBlock<Data_T>(m_fileId, id);
1347  Data_T tmpValue = block.value(vi, vj, vk, m_blockOrder);
1348  m_fileManager->decBlockRef<Data_T>(m_fileId, id);
1349  return tmpValue;
1350  } else {
1351  return block.value(vi, vj, vk, m_blockOrder);
1352  }
1353  } else {
1354  return block.emptyValue;
1355  }
1356 }
1357 
1358 //----------------------------------------------------------------------------//
1359 
1361 template <class Data_T>
1362 Data_T& SparseField<Data_T>::fastLValue(int i, int j, int k)
1363 {
1364  assert (i >= base::m_dataWindow.min.x);
1365  assert (i <= base::m_dataWindow.max.x);
1366  assert (j >= base::m_dataWindow.min.y);
1367  assert (j <= base::m_dataWindow.max.y);
1368  assert (k >= base::m_dataWindow.min.z);
1369  assert (k <= base::m_dataWindow.max.z);
1370 
1371  if (m_fileManager) {
1372  assert(false && "Called fastLValue() on a dynamic-read sparse field");
1373  Msg::print(Msg::SevWarning, "Called fastLValue() on a dynamic-read "
1374  "sparse field");
1375  return m_dummy;
1376  }
1377 
1378  // Add crop window offset
1379  applyDataWindowOffset(i, j, k);
1380  // Find block coord
1381  int bi, bj, bk;
1382  getBlockCoord(i, j, k, bi, bj, bk);
1383  // Find coord in block
1384  int vi, vj, vk;
1385  getVoxelInBlock(i, j, k, vi, vj, vk);
1386  // Get the actual block
1387  int id = blockId(bi, bj, bk);
1388  Block &block = m_blocks[id];
1389  // If block is allocated, return a reference to the data
1390  if (block.isAllocated) {
1391  return block.value(vi, vj, vk, m_blockOrder);
1392  } else {
1393  // ... Otherwise, allocate block
1394  block.isAllocated = true;
1395  block.data.resize(1 << m_blockOrder << m_blockOrder << m_blockOrder);
1396  std::fill(block.data.begin(), block.data.end(), block.emptyValue);
1397  return block.value(vi, vj, vk, m_blockOrder);
1398  }
1399 }
1400 
1401 //----------------------------------------------------------------------------//
1402 
1403 template <class Data_T>
1404 long long int SparseField<Data_T>::memSize() const
1405 {
1406  long long int blockSize = m_blocks.capacity() * sizeof(Block);
1407  long long int dataSize = 0;
1408  typename std::vector<Block>::const_iterator i;
1409  for (i = m_blocks.begin(); i != m_blocks.end(); ++i) {
1410  if (i->isAllocated) {
1411  dataSize += i->data.capacity() * sizeof(Data_T);
1412  }
1413  }
1414  return sizeof(*this) + dataSize + blockSize;
1415 }
1416 
1417 //----------------------------------------------------------------------------//
1418 
1419 template <class Data_T>
1422 {
1423  if (FieldRes::dataResolution() == V3i(0))
1424  return cend();
1425  return const_iterator(*this, base::m_dataWindow, base::m_dataWindow.min,
1426  m_blockOrder);
1427 }
1428 
1429 //----------------------------------------------------------------------------//
1430 
1431 template <class Data_T>
1434 {
1435  if (subset.isEmpty())
1436  return cend(subset);
1437  return const_iterator(*this, subset, subset.min, m_blockOrder);
1438 }
1439 
1440 //----------------------------------------------------------------------------//
1441 
1442 template <class Data_T>
1445 {
1446  return const_iterator(*this, base::m_dataWindow,
1447  V3i(base::m_dataWindow.min.x,
1448  base::m_dataWindow.min.y,
1449  base::m_dataWindow.max.z + 1),
1450  m_blockOrder);
1451 }
1452 
1453 //----------------------------------------------------------------------------//
1454 
1455 template <class Data_T>
1457 SparseField<Data_T>::cend(const Box3i &subset) const
1458 {
1459  return const_iterator(*this, subset,
1460  V3i(subset.min.x,
1461  subset.min.y,
1462  subset.max.z + 1), m_blockOrder);
1463 }
1464 
1465 //----------------------------------------------------------------------------//
1466 
1467 template <class Data_T>
1470 {
1471  if (FieldRes::dataResolution() == V3i(0))
1472  return end();
1473  return iterator(*this, base::m_dataWindow,
1474  base::m_dataWindow.min, m_blockOrder); }
1475 
1476 //----------------------------------------------------------------------------//
1477 
1478 template <class Data_T>
1481 {
1482  if (subset.isEmpty())
1483  return end(subset);
1484  return iterator(*this, subset, subset.min, m_blockOrder);
1485 }
1486 
1487 //----------------------------------------------------------------------------//
1488 
1489 template <class Data_T>
1492 {
1493  return iterator(*this, base::m_dataWindow,
1494  V3i(base::m_dataWindow.min.x,
1495  base::m_dataWindow.min.y,
1496  base::m_dataWindow.max.z + 1), m_blockOrder);
1497 }
1498 
1499 //----------------------------------------------------------------------------//
1500 
1501 template <class Data_T>
1504 {
1505  return iterator(*this, subset,
1506  V3i(subset.min.x, subset.min.y, subset.max.z + 1),
1507  m_blockOrder);
1508 }
1509 
1510 //----------------------------------------------------------------------------//
1511 
1512 template <class Data_T>
1515 {
1516  if (FieldRes::dataResolution() == V3i(0))
1517  return blockEnd();
1518  return block_iterator(*this, Box3i(V3i(0), m_blockRes - V3i(1)),
1519  V3i(0));
1520 }
1521 
1522 //----------------------------------------------------------------------------//
1523 
1524 template <class Data_T>
1527 {
1528  return block_iterator(*this, Box3i(V3i(0), m_blockRes - V3i(1)),
1529  V3i(0, 0, m_blockRes.z));
1530 }
1531 
1532 //----------------------------------------------------------------------------//
1533 
1534 template <class Data_T>
1536 {
1537  // Do calculation in floating point so we can round up later
1538  V3f res(base::m_dataWindow.size() + V3i(1));
1539  V3f blockRes(res / (1 << m_blockOrder));
1540  blockRes.x = ceil(blockRes.x);
1541  blockRes.y = ceil(blockRes.y);
1542  blockRes.z = ceil(blockRes.z);
1543  V3i intBlockRes(static_cast<int>(blockRes.x),
1544  static_cast<int>(blockRes.y),
1545  static_cast<int>(blockRes.z));
1546  m_blockRes = intBlockRes;
1547  m_blockXYSize = m_blockRes.x * m_blockRes.y;
1548  // clear() won't deallocate data. Do the swap trick.
1549  //m_blocks.clear();
1550  std::vector<Block>().swap(m_blocks);
1551 
1552  m_blocks.resize(intBlockRes.x * intBlockRes.y * intBlockRes.z);
1553 }
1554 
1555 //----------------------------------------------------------------------------//
1556 
1557 template <class Data_T>
1558 int SparseField<Data_T>::blockId(int blockI, int blockJ, int blockK) const
1559 {
1560  return blockK * m_blockXYSize + blockJ * m_blockRes.x + blockI;
1561 }
1562 
1563 //----------------------------------------------------------------------------//
1564 
1566 template <class Data_T>
1567 void SparseField<Data_T>::getBlockCoord(int i, int j, int k,
1568  int &bi, int &bj, int &bk) const
1569 {
1570  assert(i >= 0);
1571  assert(j >= 0);
1572  assert(k >= 0);
1573  bi = i >> m_blockOrder;
1574  bj = j >> m_blockOrder;
1575  bk = k >> m_blockOrder;
1576 }
1577 
1578 //----------------------------------------------------------------------------//
1579 
1581 template <class Data_T>
1582 void SparseField<Data_T>::getVoxelInBlock(int i, int j, int k,
1583  int &vi, int &vj, int &vk) const
1584 {
1585  assert(i >= 0);
1586  assert(j >= 0);
1587  assert(k >= 0);
1588  vi = i & ((1 << m_blockOrder) - 1);
1589  vj = j & ((1 << m_blockOrder) - 1);
1590  vk = k & ((1 << m_blockOrder) - 1);
1591 }
1592 
1593 //----------------------------------------------------------------------------//
1594 
1595 template <class Data_T>
1596 void SparseField<Data_T>::deallocBlock(Block &block, const Data_T &emptyValue)
1597 {
1598  block.isAllocated = false;
1600  block.clear();
1601  block.emptyValue = emptyValue;
1602 }
1603 
1604 //----------------------------------------------------------------------------//
1605 
1607 
1608 //----------------------------------------------------------------------------//
1609 
1610 #endif // Include guard
const class_type & m_field
Pointer to field we're traversing.
Definition: SparseField.h:1004
int m_blockOrder
Block size.
Definition: SparseField.h:924
SparseField< double > SparseFieldd
Definition: SparseField.h:441
#define FIELD3D_NAMESPACE_HEADER_CLOSE
Definition: ns.h:58
V3i blockRes() const
Returns the resolution of the block array.
Definition: SparseField.h:1249
bool isAnyLess(const Data_T &left, const Data_T &right)
Definition: SparseField.h:517
Imath::Box3i Box3i
Definition: SpiMathLib.h:77
void addReference(const std::string &filename, const std::string &layerPath, int valuesPerBlock, int occupiedBlocks)
Internal function to create a Reference for the current field, for use in dynamic reading...
Definition: SparseField.h:1089
V3i m_blockRes
Block array resolution.
Definition: SparseField.h:396
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:465
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:1258
Data_T & value(int i, int j, int k, int blockOrder)
Gets the value of a given voxel.
Definition: SparseField.h:98
iterator begin()
Iterator to first element.
Definition: SparseField.h:1469
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:1218
bool voxelIsInAllocatedBlock(int i, int j, int k) const
Checks if a voxel is in an allocated block.
Definition: SparseField.h:1198
int m_fileId
File id. Used with m_fileManager if active. Otherwise -1.
Definition: SparseField.h:406
SparseField< float > SparseFieldf
Definition: SparseField.h:440
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:1020
Box3i m_window
Window to traverse.
Definition: SparseField.h:928
Data_T fastValue(int i, int j, int k) const
Read access to voxel. Notice that this is non-virtual.
Definition: SparseField.h:1322
void applyDataWindowOffset(int &i, int &j, int &k) const
Applies data window offset.
Definition: SparseField.h:265
const Data_T & value(int i, int j, int k, int blockOrder) const
Gets the const value of a given voxel.
Definition: SparseField.h:104
int m_blockXYSize
Block array res.x * res.y.
Definition: SparseField.h:398
#define FIELD3D_CLIP
Definition: SpiMathLib.h:90
int blockId(int blockI, int blockJ, int blockK) const
Calculates the block number based on a block i,j,k index.
Definition: SparseField.h:1558
Data_T * m_p
Current pointed-to element.
Definition: SparseField.h:918
block_iterator(const class_type &field, const Box3i &window, const V3i &currentPos)
Constructor.
Definition: SparseField.h:946
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:1226
Contains functions controlling the loading of sparse fields.
void setupReferenceBlocks()
Internal function to setup the Reference's block pointers, for use with dynamic reading.
Definition: SparseField.h:1128
boost::intrusive_ptr< FieldBase > Ptr
Definition: Field.h:97
int x
Current x/y/z coord.
Definition: SparseField.h:724
~SparseField()
Destructor.
Definition: SparseField.h:1034
Data_T & dataRef()
Returns reference to start of memory.
Definition: SparseField.h:116
void print(Severity severity, const std::string &message)
Sends the string to the assigned output, prefixing the message with the severity. ...
Definition: Log.cpp:62
virtual void sizeChanged()
Subclasses should re-implement this if they need to perform memory allocations, etc. every time the size of the storage changes.
Definition: Field.h:866
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
int m_blockOrder
Block order (size = 2^blockOrder)
Definition: SparseField.h:394
std::vector< int > fileBlockIndices
Index in file for each block.
Definition: SparseFile.h:111
boost::intrusive_ptr< SparseField > Ptr
Definition: SparseField.h:167
int m_blockStepsTicker
Ticker for how many more steps to take before resetting the pointer.
Definition: SparseField.h:922
std::vector< Block > m_blocks
Information for all blocks in the field.
Definition: SparseField.h:400
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:572
void setupNextBlock(int i, int j, int k)
Convenience.
Definition: SparseField.h:896
std::string layerPath
Definition: SparseFile.h:106
virtual Data_T & lvalue(int i, int j, int k)
Write access to a voxel. The coordinates are global coordinates.
Definition: SparseField.h:1314
SparseField()
Constructs an empty buffer.
Definition: SparseField.h:1014
SparseField< V3f > SparseField3f
Definition: SparseField.h:443
SparseField< Data_T > class_type
Definition: SparseField.h:175
Box3i m_dataWindow
Defines the area where data is allocated. This should be treated as a closed (i.e. inclusive) interval.
Definition: Field.h:299
virtual std::string className() const
Returns the class name of the object. Used by the class pool and when writing the data to disk...
Definition: SparseField.h:298
std::vector< Data_T > data
Container for this block's data. It's either size 0 or size m_blockSize^3.
Definition: SparseField.h:130
#define BLOCK_ORDER
Definition: SparseField.h:56
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:127
SparseField< half > SparseFieldh
Definition: SparseField.h:439
Imath::Vec3< half > V3h
Definition: SpiMathLib.h:72
Sparse::SparseBlock< Data_T > Block
Definition: SparseField.h:894
iterator end()
Iterator pointing one element past the last valid one.
Definition: SparseField.h:1491
Imath::V3i V3i
Definition: SpiMathLib.h:71
static const char * classType()
Definition: SparseField.h:183
static TemplatedFieldType< SparseField< Data_T > > ms_classType
Definition: SparseField.h:415
SparseField< Data_T > class_type
Definition: SparseField.h:806
BlockPtrs blocks
Pointers to each block. This is so we can go in and manipulate them as we please. ...
Definition: SparseFile.h:117
Namespace for sparse field specifics.
Definition: SparseField.h:79
void copySparseField(const SparseField &o)
Copies internal data, including blocks, from another SparseField, used by copy constructor and operat...
Definition: SparseField.h:1061
Checks if all the absolute values in the SparseBlock are greater than some number. Useful for making narrow band levelsets Used by SparseField::releaseBlocks().
Definition: SparseField.h:558
virtual void clear(const Data_T &value)
Clears all the voxels in the storage.
Definition: SparseField.h:1158
void resize(int n)
Alloc data.
Definition: SparseField.h:108
static const char * staticClassName()
Definition: SparseField.h:178
const Data_T * m_p
Current pointed-to element.
Definition: SparseField.h:777
bool blockIsAllocated(int bi, int bj, int bk) const
Checks if a block is allocated.
Definition: SparseField.h:1209
Data_T & fastLValue(int i, int j, int k)
Write access to voxel. Notice that this is non-virtual.
Definition: SparseField.h:1362
CheckMaxAbs(Data_T maxValue)
Constructor. Takes max value.
Definition: SparseField.h:561
Box3i m_currentBlockWindow
Bounding box in voxel coordinates for the current block.
Definition: SparseField.h:1006
Imath::V3d V3d
Definition: SpiMathLib.h:74
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:1306
Data_T m_dummy
Dummy value used when needing to return but indicating a failed call.
Definition: SparseField.h:409
Box3i m_window
Bounding box for block indices.
Definition: SparseField.h:1002
void setBlockOrder(int order)
Sets the block order (i.e. the power-of-2 to use as block size.
Definition: SparseField.h:1173
Imath::V3f V3f
Definition: SpiMathLib.h:73
iterator(class_type &field, const Box3i &window, const V3i &currentPos, int blockOrder)
Definition: SparseField.h:807
block_iterator blockBegin() const
Definition: SparseField.h:1514
int m_blockOrder
Block size.
Definition: SparseField.h:786
void setupBlocks()
Initializes the block structure. Will clear any existing data.
Definition: SparseField.h:1535
bool isAllocated
Whether the block is allocated or not.
Definition: SparseField.h:122
Used to return a string for the name of a templated field.
Definition: Traits.h:116
V3i const dataResolution() const
Definition: Field.h:258
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:301
virtual long long int memSize() const
Returns the memory usage (in bytes)
Definition: SparseField.h:1404
int x
Current block index.
Definition: SparseField.h:987
Storage for one individual block of a SparseField.
Definition: SparseField.h:85
SparseField< Data_T > class_type
Convenience typedef.
Definition: SparseField.h:944
std::string filename
Definition: SparseFile.h:105
bool blockIndexIsValid(int bi, int bj, int bk) const
Returns whether a block index is valid.
Definition: SparseField.h:1240
Box3i m_window
Window to traverse.
Definition: SparseField.h:790
void clear()
Remove data.
Definition: SparseField.h:112
Contains Field, WritableField and ResizableField classes.
block_iterator blockEnd() const
Const iterator pointing to element one past the last valid block.
Definition: SparseField.h:1526
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:1582
const_iterator cend() const
Const iterator pointing one element past the last valid one.
Definition: SparseField.h:1444
SparseField< V3d > SparseField3d
Definition: SparseField.h:444
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:1567
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:1107
const class_type * m_field
Reference to field we're traversing.
Definition: SparseField.h:792
std::vector< Ptr > Vec
Definition: SparseField.h:168
Sparse::SparseBlock< Data_T > Block
Definition: SparseField.h:367
const_iterator(const class_type &field, const Box3i &window, const V3i &currentPos, int blockOrder)
Definition: SparseField.h:634
CubicGenericFieldInterp< SparseField< Data_T > > CubicInterp
Definition: SparseField.h:171
ResizableField< Data_T > base
Definition: SparseField.h:366
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:1048
bool m_isEmptyBlock
Whether we're at an empty block and we don't increment m_p.
Definition: SparseField.h:920
bool m_isEmptyBlock
Whether we're at an empty block and we don't increment m_p.
Definition: SparseField.h:779
int blockOrder() const
Returns the block order.
Definition: SparseField.h:1182
bool m_blockIsActivated
Used with delayed-load fields. Check if we've already activated the current blocks.
Definition: SparseField.h:782
Sparse::SparseBlock< Data_T > Block
Definition: SparseField.h:730
void deallocBlock(Block &block, const Data_T &emptyValue)
Deallocated the data of the given block and sets its empty value.
Definition: SparseField.h:1596
This Field subclass stores voxel data in block-allocated arrays.
Definition: SparseField.h:160
static SparseFileManager & singleton()
Returns a reference to the singleton instance.
Definition: SparseFile.cpp:63
virtual void sizeChanged()
Subclasses should re-implement this if they need to perform memory allocations, etc. every time the size of the storage changes.
Definition: SparseField.h:371
Checks if all the values in the SparseBlock are equal. Used by SparseField::releaseBlocks().
Definition: SparseField.h:455
const Box3i & blockBoundingBox()
Returns a reference to the bounding box representing the current block.
Definition: SparseField.h:982
SparseField< V3h > SparseField3h
Definition: SparseField.h:442
FIELD3D_CLASSTYPE_TEMPL_INSTANTIATION(SparseField)
DEFINE_FIELD_RTTI_CONCRETE_CLASS
Definition: SparseField.h:176
LinearGenericFieldInterp< SparseField< Data_T > > LinearInterp
Definition: SparseField.h:170
SparseField< Data_T > class_type
Definition: SparseField.h:633
SparseFileManager * m_manager
Pointer to the singleton file manager.
Definition: SparseField.h:794
SparseFileManager * m_fileManager
Pointer to SparseFileManager. Used when doing dynamic reading. NULL if not in use.
Definition: SparseField.h:404
int m_blockStepsTicker
Ticker for how many more steps to take before resetting the pointer.
Definition: SparseField.h:784
const_iterator cbegin() const
Const iterator to first element. "cbegin" matches the tr1 c++ standard.
Definition: SparseField.h:1421
int blockSize() const
Returns the block size.
Definition: SparseField.h:1190
void setupNextBlock(int i, int j, int k)
Definition: SparseField.h:734
class_type * m_field
Reference to field we're traversing.
Definition: SparseField.h:930
std::string name
Optional name of the field.
Definition: Field.h:173