44#ifndef _INCLUDED_Field3D_SparseField_H_
45#define _INCLUDED_Field3D_SparseField_H_
51#include <boost/thread/mutex.hpp>
52#include <boost/lexical_cast.hpp>
69template <
class Field_T>
71template <
class Field_T>
85template <
typename Data_T>
93 typedef boost::intrusive_ptr<LinearSparseFieldInterp>
Ptr;
102 return "LinearSparseFieldInterp";
120 V3i c1(
static_cast<int>(floor(
p.x)),
121 static_cast<int>(floor(
p.y)),
122 static_cast<int>(floor(
p.z)));
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));
148 if (
vi < blockSize - 1 &&
vj < blockSize - 1 &&
vk < blockSize - 1) {
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);
164 const Data_T *
const c122 =
c112 + blockSize * (
c2.y -
c1.y);
166 Data_T value =
static_cast<Data_T
>
185 return static_cast<Data_T
>
226template <
typename Data_T>
249 inline Data_T&
value(
int i,
int j,
int k,
int blockOrder)
251 {
return data[(
k << blockOrder << blockOrder) + (
j << blockOrder) +
i]; }
255 inline const Data_T&
value(
int i,
int j,
int k,
int blockOrder)
const
256 {
return data[(
k << blockOrder << blockOrder) + (
j << blockOrder) +
i]; }
267 data =
new Data_T[
n];
287 if (
other.isAllocated) {
349template <
class Data_T>
357 typedef boost::intrusive_ptr<SparseField>
Ptr;
358 typedef std::vector<Ptr>
Vec;
370 return "SparseField";
438 template <
typename Functor_T>
487 virtual Data_T
value(
int i,
int j,
int k)
const;
488 virtual long long int memSize()
const;
496 virtual Data_T&
lvalue(
int i,
int j,
int k);
528 class const_iterator;
531 const_iterator
cbegin()
const;
535 const_iterator
cend()
const;
558 class block_iterator;
570 void addReference(
const std::string &filename,
const std::string &layerPath,
571 int valuesPerBlock,
int numVoxels,
int occupiedBlocks);
655template <
typename Data_T>
675template <
typename Data_T>
709template <
typename Data_T>
727 size_t len = blockSize.x * blockSize.y * blockSize.z;
730 for (
size_t i = 0;
i <
len;
i++) {
739 for (
size_t i = 0;
i <
len;
i++, x++) {
740 if (x >= blockSize.x) {
743 if (y >= blockSize.y) {
769template <
typename Data_T>
810template <
typename Data_T>
832 size_t len = blockSize.x * blockSize.y * blockSize.z;
836 for (
size_t i = 0;
i <
len;
i++) {
845 for (
size_t i = 0;
i <
len;
i++, x++) {
846 if (x >= blockSize.x) {
849 if (y >= blockSize.y) {
884template <
class Data_T>
888#if defined(WIN32) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
894 typedef Data_T& reference;
904 m_blockId(-1), m_window(
window), m_field(&field)
906 m_manager = m_field->m_fileManager;
907 setupNextBlock(x, y, z);
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);
920 if (x == m_window.max.x) {
921 if (y == m_window.max.y) {
935 ++m_blockStepsTicker;
937 if (!m_isEmptyBlock && (!m_manager || m_blockIsActivated))
944 m_blockStepsTicker = 0;
945 setupNextBlock(x, y, z);
949 template <
class Iter_T>
952 return x ==
rhs.x && y ==
rhs.y && z ==
rhs.z;
954 template <
class Iter_T>
957 return x !=
rhs.x || y !=
rhs.y || z !=
rhs.z;
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];
966 m_field->getVoxelInBlock(x, y, z,
vi,
vj,
vk);
971 inline const Data_T* operator -> ()
const
973 if (!m_isEmptyBlock && m_manager && !m_blockIsActivated) {
976 m_blockIsActivated =
true;
977 const Block &
block = m_field->m_blocks[m_blockId];
979 m_field->getVoxelInBlock(x, y, z,
vi,
vj,
vk);
1000 m_field->applyDataWindowOffset(
i,
j,
k);
1001 m_field->getBlockCoord(
i,
j,
k, m_blockI, m_blockJ, m_blockK);
1003 m_blockId = m_field->blockId(m_blockI, m_blockJ, m_blockK);
1006 oldBlockId <
static_cast<int>(m_field->m_numBlocks) &&
1008 m_manager->decBlockRef<Data_T>(m_field->m_fileId,
oldBlockId);
1010 if (m_blockId >= m_field->m_blockXYSize * m_field->m_blockRes.z) {
1011 m_isEmptyBlock =
true;
1015 const Block &
block = m_field->m_blocks[m_blockId];
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);
1030 m_isEmptyBlock =
false;
1032 m_p = &
block.emptyValue;
1033 m_isEmptyBlock =
true;
1035 if (m_field->m_fileManager) {
1036 m_blockIsActivated =
false;
1066template <
class Data_T>
1070#if defined(WIN32) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
1076 typedef Data_T& reference;
1085 m_blockId(-1), m_window(
window), m_field(&field)
1087 setupNextBlock(x, y, z);
1093 if (x == m_window.max.x) {
1094 if (y == m_window.max.y) {
1108 ++m_blockStepsTicker;
1110 if (!m_isEmptyBlock)
1117 m_blockStepsTicker = 0;
1118 setupNextBlock(x, y, z);
1124 return x ==
rhs.x && y ==
rhs.y && z ==
rhs.z;
1128 return x !=
rhs.x || y !=
rhs.y || z !=
rhs.z;
1132 if (m_field->m_fileManager) {
1133 assert(
false &&
"Dereferencing iterator on a dynamic-read sparse field");
1139 if (m_isEmptyBlock) {
1141 m_field->lvalue(x, y, z);
1143 setupNextBlock(x, y, z);
1147 inline Data_T* operator -> ()
1149 if (m_field->m_fileManager) {
1150 assert(
false &&
"Dereferencing iterator on a dynamic-read sparse field");
1156 if (m_isEmptyBlock) {
1158 m_field->lvalue(x, y, z);
1160 setupNextBlock(x, y, z);
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;
1180 m_field->getVoxelInBlock(
i,
j,
k,
vi,
vj,
vk);
1181 m_blockStepsTicker =
vi;
1182 if (
block.isAllocated) {
1184 m_isEmptyBlock =
false;
1186 m_p = &
block.emptyValue;
1187 m_isEmptyBlock =
true;
1212template <
class Data_T>
1222 m_window(
window), m_field(field)
1224 recomputeBlockBoundingBox();
1229 if (x == m_window.max.x) {
1230 if (y == m_window.max.y) {
1241 recomputeBlockBoundingBox();
1247 return x ==
rhs.x && y ==
rhs.y && z ==
rhs.z;
1252 return x !=
rhs.x || y !=
rhs.y || z !=
rhs.z;
1257 return m_currentBlockWindow;
1272 m_currentBlockWindow =
box;
1286template <
class Data_T>
1298template <
class Data_T>
1301 m_blockOrder(
o.m_blockOrder),
1303 m_fileManager(
o.m_fileManager)
1310template <
class Data_T>
1313 if (m_fileManager) {
1317 m_fileManager->removeFieldFromCache<Data_T>(m_fileId);
1326template <
class Data_T>
1331 this->base::operator=(
o);
1339template <
class Data_T>
1343 m_blockOrder =
o.m_blockOrder;
1344 if (
o.m_fileManager) {
1347 m_fileManager =
o.m_fileManager;
1349 m_fileManager->reference<Data_T>(
o.m_fileId);
1355 setupReferenceBlocks();
1358 m_blockRes =
o.m_blockRes;
1359 m_blockXYSize =
o.m_blockXYSize;
1363 m_numBlocks =
o.m_numBlocks;
1364 m_blocks =
new Block[m_numBlocks];
1365 for (
size_t i = 0;
i < m_numBlocks; ++
i) {
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);
1372 m_fileManager =
NULL;
1378template <
class Data_T>
1380 const std::string &layerPath,
1386 m_fileId = m_fileManager->getNextId<Data_T>(filename, layerPath);
1389 m_fileManager->reference<Data_T>(m_fileId);
1391 reference->numVoxels = numVoxels;
1392 reference->occupiedBlocks = occupiedBlocks;
1393 reference->setNumBlocks(m_numBlocks);
1398template <
class Data_T>
1401 if (m_numBlocks !=
o.m_numBlocks)
return;
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();
1412template <
class Data_T>
1415 if (!m_fileManager || m_fileId < 0)
return;
1418 m_fileManager->reference<Data_T>(m_fileId);
1420#if F3D_NO_BLOCKS_ARRAY
1422 reference->
blocks = m_blocks;
1424 for (
size_t i = 0;
i < m_numBlocks; ++
i, ++
fb) {
1425 if (m_blocks[
i].isAllocated) {
1435 reference->
blocks.begin();
1437 for (
size_t i = 0;
i < m_numBlocks; ++
i, ++
fb, ++
bp) {
1438 if (m_blocks[
i].isAllocated) {
1451template <
class Data_T>
1456 Block *
p = m_blocks, *end = m_blocks + m_numBlocks;
1465template <
class Data_T>
1468 m_blockOrder =
order;
1474template <
class Data_T>
1477 return m_blockOrder;
1482template <
class Data_T>
1485 return 1 << m_blockOrder;
1490template <
class Data_T>
1494 applyDataWindowOffset(
i,
j,
k);
1496 return blockIsAllocated(
bi,
bj,
bk);
1501template <
class Data_T>
1510template <
class Data_T>
1513 return m_blocks[blockId(
bi,
bj,
bk)].emptyValue;
1518template <
class Data_T>
1523 if (
block.isAllocated) {
1532template <
class Data_T>
1535 return bi >= 0 &&
bj >= 0 &&
bk >= 0 &&
1536 bi < m_blockRes.x &&
bj < m_blockRes.y &&
bk < m_blockRes.z;
1541template <
class Data_T>
1549template <
class Data_T>
1550template <
typename Functor_T>
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) {
1569 if (
by >= m_blockRes.y) {
1575 if (
bx == m_blockRes.x-1) {
1578 if (
by == m_blockRes.y-1) {
1581 if (
bz == m_blockRes.z-1) {
1585 if (m_blocks[
i].isAllocated) {
1587 deallocBlock(m_blocks[
i], emptyValue);
1597template <
class Data_T>
1600 return fastValue(
i,
j,
k);
1605template <
class Data_T>
1608 return fastLValue(
i,
j,
k);
1613template <
class Data_T>
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);
1623 applyDataWindowOffset(
i,
j,
k);
1631 int id = blockId(
bi,
bj,
bk);
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);
1639 m_fileManager->decBlockRef<Data_T>(m_fileId, id);
1645 return block.emptyValue;
1652template <
class Data_T>
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);
1662 if (m_fileManager) {
1663 assert(
false &&
"Called fastLValue() on a dynamic-read sparse field");
1670 applyDataWindowOffset(
i,
j,
k);
1678 int id = blockId(
bi,
bj,
bk);
1681 if (
block.isAllocated) {
1685 size_t blockSize = 1 << m_blockOrder << m_blockOrder << m_blockOrder;
1686 block.resize(blockSize);
1693template <
class Data_T>
1696 int id = blockId(
bi,
bj,
bk);
1698 if (
block.isAllocated) {
1707template <
class Data_T>
1710 long long int blockSize = m_numBlocks *
sizeof(
Block);
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) *
1720 return sizeof(*this) +
dataSize + blockSize;
1725template <
class Data_T>
1729 const size_t blockSize = (1 << m_blockOrder << m_blockOrder << m_blockOrder);
1731 for (
size_t i = 0;
i < m_numBlocks; ++
i) {
1732 if (m_blocks[
i].isAllocated) {
1742template <
class Data_T>
1748 return const_iterator(*
this, base::m_dataWindow, base::m_dataWindow.min,
1754template <
class Data_T>
1765template <
class Data_T>
1770 V3i(base::m_dataWindow.min.x,
1771 base::m_dataWindow.min.y,
1772 base::m_dataWindow.max.z + 1),
1778template <
class Data_T>
1785 subset.max.z + 1), m_blockOrder);
1790template <
class Data_T>
1796 return iterator(*
this, base::m_dataWindow,
1797 base::m_dataWindow.min, m_blockOrder); }
1801template <
class Data_T>
1812template <
class Data_T>
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);
1824template <
class Data_T>
1835template <
class Data_T>
1847template <
class Data_T>
1852 V3i(0, 0, m_blockRes.z));
1857template <
class Data_T>
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);
1867 static_cast<int>(blockRes.y),
1868 static_cast<int>(blockRes.z));
1870 m_blockXYSize = m_blockRes.x * m_blockRes.y;
1875 m_blocks =
new Block[m_numBlocks];
1880template <
class Data_T>
1889template <
class Data_T>
1891 int &
bi,
int &
bj,
int &
bk)
const
1896 bi =
i >> m_blockOrder;
1897 bj =
j >> m_blockOrder;
1898 bk =
k >> m_blockOrder;
1904template <
class Data_T>
1906 int &
vi,
int &
vj,
int &
vk)
const
1911 vi =
i & ((1 << m_blockOrder) - 1);
1912 vj =
j & ((1 << m_blockOrder) - 1);
1913 vk =
k & ((1 << m_blockOrder) - 1);
1918template <
class Data_T>
1921 m_fileManager->incBlockRef<Data_T>(m_fileId, blockId);
1926template <
class Data_T>
1929 m_fileManager->activateBlock<Data_T>(m_fileId, blockId);
1934template <
class Data_T>
1937 m_fileManager->decBlockRef<Data_T>(m_fileId, blockId);
1942template <
class Data_T>
1950template <
class Data_T>
1954 const size_t blockSide = (1 << m_blockOrder);
1969template <
class Data_T>
1972 block.isAllocated =
false;
1975 block.emptyValue = emptyValue;
FIELD3D_VEC3_T< T > operator*(S s, const FIELD3D_VEC3_T< T > vec)
Scalar times Vec3 multiplication. Makes the interpolation calls cleaner.
Contains Field, WritableField and ResizableField classes.
Box3d continuousBounds(const Box3i &bbox)
Box3i clipBounds(const Box3i &bbox, const Box3i &bounds)
#define FIELD3D_CLASSTYPE_TEMPL_INSTANTIATION(field)
V3i indexToCoord(const size_t idx, const V3i &res)
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.
SparseField< V3h > SparseField3h
SparseField< V3d > SparseField3d
SparseField< float > SparseFieldf
SparseField< half > SparseFieldh
SparseField< V3f > SparseField3f
Box3i blockCoords(const Box3i &dvsBounds, const SparseField< Data_T > *f)
SparseField< double > SparseFieldd
Contains functions controlling the loading of sparse fields.
boost::intrusive_ptr< FieldBase > Ptr
std::string name
Optional name of the field.
V3i const dataResolution() const
Box3i m_dataWindow
Defines the area where data is allocated. This should be treated as a closed (i.e....
const Box3i & dataWindow() const
Returns the data window. Any coordinate inside this window is safe to pass to value() in the Field su...
Data_T value_type
Allows us to reference the template class.
LinearSparseFieldInterp class_type
boost::intrusive_ptr< LinearSparseFieldInterp > Ptr
value_type sample(const SparseField< Data_T > &field, const V3d &vsP) const
static const char * staticClassType()
static TemplatedFieldType< LinearSparseFieldInterp< Data_T > > ms_classType
RefBase base
Convenience typedef for referring to base class.
DEFINE_FIELD_RTTI_CONCRETE_CLASS
static const char * staticClassName()
virtual void sizeChanged()
Subclasses should re-implement this if they need to perform memory allocations, etc....
const class_type & m_field
Pointer to field we're traversing.
SparseField< Data_T > class_type
Convenience typedef.
Box3i m_window
Bounding box for block indices.
int x
Current block index.
void recomputeBlockBoundingBox()
const Box3i & blockBoundingBox()
Returns a reference to the bounding box representing the current block.
Box3i m_currentBlockWindow
Bounding box in voxel coordinates for the current block.
block_iterator(const class_type &field, const Box3i &window, const V3i ¤tPos)
Constructor.
bool m_blockIsActivated
Used with delayed-load fields. Check if we've already activated the current blocks.
Box3i m_window
Window to traverse.
int m_blockStepsTicker
Ticker for how many more steps to take before resetting the pointer.
void setupNextBlock(int i, int j, int k)
const_iterator(const class_type &field, const Box3i &window, const V3i ¤tPos, int blockOrder)
Sparse::SparseBlock< Data_T > Block
SparseFileManager * m_manager
Pointer to the singleton file manager.
bool m_isEmptyBlock
Whether we're at an empty block and we don't increment m_p.
const class_type * m_field
Reference to field we're traversing.
int m_blockOrder
Block size.
int x
Current x/y/z coord.
int m_blockI
Current block index.
SparseField< Data_T > class_type
const Data_T * m_p
Current pointed-to element.
int m_blockOrder
Block size.
Sparse::SparseBlock< Data_T > Block
int m_blockI
Current block index.
Box3i m_window
Window to traverse.
int m_blockStepsTicker
Ticker for how many more steps to take before resetting the pointer.
void setupNextBlock(int i, int j, int k)
Convenience.
iterator(class_type &field, const Box3i &window, const V3i ¤tPos, int blockOrder)
bool m_isEmptyBlock
Whether we're at an empty block and we don't increment m_p.
SparseField< Data_T > class_type
class_type * m_field
Reference to field we're traversing.
Data_T * m_p
Current pointed-to element.
This Field subclass stores voxel data in block-allocated arrays.
CubicGenericFieldInterp< SparseField< Data_T > > CubicInterp
bool isDynamicLoad() const
Whether the field is dynamically loaded.
size_t numGrains() const
Number of 'grains' to use with threaded access.
void setBlockOrder(int order)
Sets the block order (i.e. the power-of-2 to use as block size.
Sparse::SparseBlock< Data_T > Block
virtual void sizeChanged()
Subclasses should re-implement this if they need to perform memory allocations, etc....
SparseFileManager * m_fileManager
Pointer to SparseFileManager. Used when doing dynamic reading. NULL if not in use.
bool getGrainBounds(const size_t idx, Box3i &vsBounds) const
Bounding box of the given 'grain'.
iterator end()
Iterator pointing one element past the last valid one.
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.
void setupBlocks()
Initializes the block structure. Will clear any existing data.
block_iterator blockEnd() const
Const iterator pointing to element one past the last valid block.
int releaseBlocks(Functor_T func)
Releases any blocks that are deemed empty. This can be used to clean up after algorithms that write "...
void applyDataWindowOffset(int &i, int &j, int &k) const
Applies data window offset.
block_iterator blockBegin() const
static const char * staticClassName()
V3i blockRes() const
Returns the resolution of the block array.
iterator begin()
Iterator to first element.
virtual void clear(const Data_T &value)
Clears all the voxels in the storage.
FIELD3D_CLASSNAME_CLASSTYPE_IMPLEMENTATION
DEFINE_FIELD_RTTI_CONCRETE_CLASS
static TemplatedFieldType< SparseField< Data_T > > ms_classType
Block * m_blocks
Array of blocks. Not using std::vector since SparseBlock is noncopyable.
virtual Data_T & lvalue(int i, int j, int k)
Write access to a voxel. The coordinates are global coordinates.
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..
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.
int m_blockXYSize
Block array res.x * res.y.
bool blockIndexIsValid(int bi, int bj, int bk) const
Returns whether a block index is valid.
ResizableField< Data_T > base
int m_fileId
File id. Used with m_fileManager if active. Otherwise -1.
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.
bool blockIsAllocated(int bi, int bj, int bk) const
Checks if a block is allocated.
void decBlockRef(const int blockId) const
Decrements the block ref count for the given block.
void deallocBlock(Block &block, const Data_T &emptyValue)
Deallocated the data of the given block and sets its empty value.
static const char * staticClassType()
Data_T m_dummy
Dummy value used when needing to return but indicating a failed call.
~SparseField()
Destructor.
SparseField()
Constructs an empty buffer.
SparseField< Data_T > class_type
size_t m_numBlocks
Number of blocks in field.
boost::intrusive_ptr< SparseField > Ptr
Data_T fastValue(int i, int j, int k) const
Read access to voxel. Notice that this is non-virtual.
bool voxelIsInAllocatedBlock(int i, int j, int k) const
Checks if a voxel is in an allocated block.
friend class SparseFieldIO
void activateBlock(const int blockId) const
Activates a given block.
Data_T & fastLValue(int i, int j, int k)
Write access to voxel. Notice that this is non-virtual.
int m_blockOrder
Block order (size = 2^blockOrder)
LinearSparseFieldInterp< Data_T > LinearInterp
const_iterator cend() const
Const iterator pointing one element past the last valid one.
virtual FieldBase::Ptr clone() const
Returns a pointer to a copy of the field, pure virtual so ensure derived classes properly implement i...
virtual long long int memSize() const
Returns the memory usage (in bytes)
SparseField & operator=(const SparseField &o)
Assignment operator. For cache-managed fields, it creates a new file reference, and for non-managed f...
int blockSize() const
Returns the block size.
int blockOrder() const
Returns the block order.
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.
void setupReferenceBlocks()
Internal function to setup the Reference's block pointers, for use with dynamic reading.
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.
V3i m_blockRes
Block array resolution.
virtual size_t voxelCount() const
Counts the number of voxels. For most fields, this is just the volume of the data window,...
virtual Data_T value(int i, int j, int k) const
Read access to a voxel. The coordinates are in integer voxel space .
void copyBlockStates(const SparseField< Data_T > &o)
Internal function to copy empty values and allocated flags, without copying data, used when copying a...
void copySparseField(const SparseField &o)
Copies internal data, including blocks, from another SparseField, used by copy constructor and operat...
const_iterator cbegin() const
Const iterator to first element. "cbegin" matches the tr1 c++ standard.
int blockId(int blockI, int blockJ, int blockK) const
Calculates the block number based on a block i,j,k index.
void incBlockRef(const int blockId) const
Increments the block ref count for the given block.
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,...
static SparseFileManager & singleton()
Returns a reference to the singleton instance.
BlockPtrs blocks
Pointers to each block. This is so we can go in and manipulate them as we please.
std::vector< int > fileBlockIndices
Index in file for each block.
FIELD3D_API void print(Severity severity, const std::string &message)
Sends the string to the assigned output, prefixing the message with the severity.
Namespace for sparse field specifics.
bool isAnyLess(const Data_T &left, const Data_T &right)
#define FIELD3D_NAMESPACE_HEADER_CLOSE
Checks if all the values in the SparseBlock are equal. Used by SparseField::releaseBlocks().
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...
Checks if all the absolute values in the SparseBlock are greater than some number....
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...
CheckMaxAbs(Data_T maxValue)
Constructor. Takes max value.
Storage for one individual block of a SparseField.
bool isAllocated
Whether the block is allocated or not.
const SparseBlock & operator=(const SparseBlock &)
Non-copyable.
void copy(const SparseBlock &other, size_t n)
Copy data from another block.
SparseBlock(const SparseBlock &)
Non-copyable.
void resize(int n)
Alloc data.
const Data_T & value(int i, int j, int k, int blockOrder) const
Gets the const value of a given voxel.
Data_T emptyValue
The value to use if the block isn't allocated. We allow setting this per block so that we for example...
Data_T & value(int i, int j, int k, int blockOrder)
Gets the value of a given voxel.
Data_T * data
Pointer to data. Null if block is unallocated.
static boost::mutex ms_resizeMutex
Prevents concurrent allocation of blocks. There should be little contention, and this prevents multip...
Used to return a string for the name of a templated field.