44 #ifndef _INCLUDED_Field3D_SparseField_H_
45 #define _INCLUDED_Field3D_SparseField_H_
51 #include <boost/thread/mutex.hpp>
52 #include <boost/lexical_cast.hpp>
57 #define BLOCK_ORDER 4 // 2^BLOCK_ORDER is the block size along each axis
69 template <
class Field_T>
71 template <
class Field_T>
85 template <
typename Data_T>
93 typedef boost::intrusive_ptr<LinearSparseFieldInterp>
Ptr;
102 return "LinearSparseFieldInterp";
117 FIELD3D_VEC3_T<double> p(vsP - FIELD3D_VEC3_T<double>(0.5));
120 V3i c1(static_cast<int>(
floor(p.x)),
121 static_cast<int>(
floor(p.y)),
122 static_cast<int>(
floor(p.z)));
126 FIELD3D_VEC3_T<double> f1(
static_cast<FIELD3D_VEC3_T<double>
>(c2) - p);
128 FIELD3D_VEC3_T<double> f2(
static_cast<FIELD3D_VEC3_T<double>
>(1.0) - f1);
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));
141 int i = c1.x, j = c1.y, k = c1.z, vi, vj, vk, bi, bj, bk;
148 if (vi < blockSize - 1 && vj < blockSize - 1 && vk < blockSize - 1) {
151 const int blockId = field.
blockId(bi, bj, bk);
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);
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 +
169 f2.y * (f1.z * *c121 +
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))));
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))));
226 template <
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];
349 template <
class Data_T>
357 typedef boost::intrusive_ptr<SparseField>
Ptr;
358 typedef std::vector<Ptr>
Vec;
370 return "SparseField";
438 template <
typename Functor_T>
442 int blockId(
int blockI,
int blockJ,
int blockK)
const;
447 void getBlockCoord(
int i,
int j,
int k,
int &bi,
int &bj,
int &bk)
const;
452 void getVoxelInBlock(
int i,
int j,
int k,
int &vi,
int &vj,
int &vk)
const;
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);
502 Data_T
fastValue(
int i,
int j,
int k)
const;
508 Data_T*
blockData(
int bi,
int bj,
int bk)
const;
528 class const_iterator;
531 const_iterator
cbegin()
const;
535 const_iterator
cend()
const;
538 const_iterator
cend(
const Box3i &subset)
const;
558 class block_iterator;
570 void addReference(
const std::string &filename,
const std::string &layerPath,
571 int valuesPerBlock,
int occupiedBlocks);
603 void deallocBlock(Block &block,
const Data_T &emptyValue);
655 template <
typename Data_T>
656 boost::mutex SparseBlock<Data_T>::ms_resizeMutex;
675 template <
typename Data_T>
680 f->
getBlockCoord(dvsBounds.min.x, dvsBounds.min.y, dvsBounds.min.z,
681 dbsBounds.min.x, dbsBounds.min.y, dbsBounds.min.z);
682 f->
getBlockCoord(dvsBounds.max.x, dvsBounds.max.y, dvsBounds.max.z,
683 dbsBounds.max.x, dbsBounds.max.y, dbsBounds.max.z);
696 template <
typename Data_T>
708 const V3i &validSize,
const V3i &blockSize)
711 Data_T first = block.
data[0];
714 size_t len = blockSize.x * blockSize.y * blockSize.z;
715 if (validSize == blockSize) {
717 for (
size_t i = 0; i < len; i++) {
718 if (block.
data[i] != first) {
726 for (
size_t i = 0; i < len; i++, x++) {
727 if (x >= blockSize.x) {
730 if (y >= blockSize.y) {
735 if (x >= validSize.x || y >= validSize.y || z >= validSize.z) {
738 if (block.
data[i] != first) {
746 retEmptyValue = first;
756 template <
typename Data_T>
757 inline bool isAnyLess(
const Data_T &left,
const Data_T &right)
759 return (std::abs(left) < right);
767 return (std::abs(left.x) < right.x ||
768 std::abs(left.y) < right.y ||
769 std::abs(left.z) < right.z );
777 return (std::abs(left.x) < right.x ||
778 std::abs(left.y) < right.y ||
779 std::abs(left.z) < right.z );
787 return (std::abs(left.x) < right.x ||
788 std::abs(left.y) < right.y ||
789 std::abs(left.z) < right.z );
797 template <
typename Data_T>
813 const V3i &validSize,
const V3i &blockSize)
816 Data_T first = block.
data[0];
818 bool allGreater =
true;
819 size_t len = blockSize.x * blockSize.y * blockSize.z;
821 if (validSize == blockSize) {
823 for (
size_t i = 0; i < len; i++) {
832 for (
size_t i = 0; i < len; i++, x++) {
833 if (x >= blockSize.x) {
836 if (y >= blockSize.y) {
841 if (x >= validSize.x || y >= validSize.y || z >= validSize.z) {
852 retEmptyValue = first;
871 template <
class Data_T>
875 #if defined(WIN32) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
876 typedef std::forward_iterator_tag iterator_category;
878 typedef ptrdiff_t difference_type;
879 typedef ptrdiff_t distance_type;
880 typedef Data_T *pointer;
881 typedef Data_T& reference;
888 : x(currentPos.x), y(currentPos.y), z(currentPos.z),
889 m_p(NULL), m_blockIsActivated(false),
891 m_blockId(-1), m_window(window), m_field(&field)
893 m_manager = m_field->m_fileManager;
894 setupNextBlock(x, y, z);
897 if (m_manager && m_blockId >= 0 &&
898 m_blockId < static_cast<int>(m_field->m_numBlocks)) {
899 if (m_field->m_blocks[m_blockId].isAllocated)
900 m_manager->decBlockRef<Data_T>(m_field->m_fileId, m_blockId);
905 bool resetPtr =
false;
907 if (x == m_window.max.x) {
908 if (y == m_window.max.y) {
922 ++m_blockStepsTicker;
924 if (!m_isEmptyBlock && (!m_manager || m_blockIsActivated))
931 m_blockStepsTicker = 0;
932 setupNextBlock(x, y, z);
936 template <
class Iter_T>
937 inline bool operator == (
const Iter_T &rhs)
const
939 return x == rhs.x && y == rhs.y && z == rhs.z;
941 template <
class Iter_T>
942 inline bool operator != (
const Iter_T &rhs)
const
944 return x != rhs.x || y != rhs.y || z != rhs.z;
948 if (!m_isEmptyBlock && m_manager && !m_blockIsActivated) {
949 m_manager->activateBlock<Data_T>(m_field->m_fileId, m_blockId);
950 m_blockIsActivated =
true;
951 const Block &block = m_field->m_blocks[m_blockId];
953 m_field->getVoxelInBlock(x, y, z, vi, vj, vk);
958 inline const Data_T* operator -> ()
const
960 if (!m_isEmptyBlock && m_manager && !m_blockIsActivated) {
962 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);
987 m_field->applyDataWindowOffset(i, j, k);
988 m_field->getBlockCoord(i, j, k, m_blockI, m_blockJ, m_blockK);
989 int oldBlockId = m_blockId;
990 m_blockId = m_field->blockId(m_blockI, m_blockJ, m_blockK);
991 if (m_manager && oldBlockId != m_blockId &&
993 oldBlockId < static_cast<int>(m_field->m_numBlocks) &&
994 m_field->m_blocks[oldBlockId].isAllocated) {
995 m_manager->decBlockRef<Data_T>(m_field->m_fileId, oldBlockId);
997 if (m_blockId >= m_field->m_blockXYSize * m_field->m_blockRes.z) {
998 m_isEmptyBlock =
true;
1002 const Block &block = m_field->m_blocks[m_blockId];
1004 m_field->getVoxelInBlock(i, j, k, vi, vj, vk);
1005 m_blockStepsTicker = vi;
1007 if (m_manager && oldBlockId != m_blockId && m_blockId >= 0) {
1008 m_manager->incBlockRef<Data_T>(m_field->m_fileId, m_blockId);
1017 m_isEmptyBlock =
false;
1020 m_isEmptyBlock =
true;
1022 if (m_field->m_fileManager) {
1023 m_blockIsActivated =
false;
1053 template <
class Data_T>
1057 #if defined(WIN32) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
1058 typedef std::forward_iterator_tag iterator_category;
1060 typedef ptrdiff_t difference_type;
1061 typedef ptrdiff_t distance_type;
1062 typedef Data_T *pointer;
1063 typedef Data_T& reference;
1068 const Box3i &window,
1070 : x(currentPos.x), y(currentPos.y), z(currentPos.z),
1071 m_p(NULL), m_blockStepsTicker(0),
m_blockOrder(blockOrder),
1072 m_blockId(-1), m_window(window), m_field(&field)
1074 setupNextBlock(x, y, z);
1078 bool resetPtr =
false;
1080 if (x == m_window.max.x) {
1081 if (y == m_window.max.y) {
1095 ++m_blockStepsTicker;
1097 if (!m_isEmptyBlock)
1104 m_blockStepsTicker = 0;
1105 setupNextBlock(x, y, z);
1111 return x == rhs.
x && y == rhs.
y && z == rhs.
z;
1115 return x != rhs.
x || y != rhs.
y || z != rhs.
z;
1119 if (m_field->m_fileManager) {
1120 assert(
false &&
"Dereferencing iterator on a dynamic-read sparse field");
1126 if (m_isEmptyBlock) {
1128 m_field->lvalue(x, y, z);
1130 setupNextBlock(x, y, z);
1134 inline Data_T* operator -> ()
1136 if (m_field->m_fileManager) {
1137 assert(
false &&
"Dereferencing iterator on a dynamic-read sparse field");
1143 if (m_isEmptyBlock) {
1145 m_field->lvalue(x, y, z);
1147 setupNextBlock(x, y, z);
1158 m_field->applyDataWindowOffset(i, j, k);
1159 m_field->getBlockCoord(i, j, k, m_blockI, m_blockJ, m_blockK);
1160 m_blockId = m_field->blockId(m_blockI, m_blockJ, m_blockK);
1161 if (m_blockId >= m_field->m_blockXYSize * m_field->m_blockRes.z) {
1162 m_isEmptyBlock =
true;
1165 Block &block = m_field->m_blocks[m_blockId];
1167 m_field->getVoxelInBlock(i, j, k, vi, vj, vk);
1168 m_blockStepsTicker = vi;
1171 m_isEmptyBlock =
false;
1174 m_isEmptyBlock =
true;
1199 template <
class Data_T>
1207 const V3i ¤tPos)
1208 : x(currentPos.x), y(currentPos.y), z(currentPos.z),
1209 m_window(window), m_field(field)
1211 recomputeBlockBoundingBox();
1216 if (x == m_window.max.x) {
1217 if (y == m_window.max.y) {
1228 recomputeBlockBoundingBox();
1234 return x == rhs.
x && y == rhs.
y && z == rhs.
z;
1239 return x != rhs.
x || y != rhs.
y || z != rhs.
z;
1244 return m_currentBlockWindow;
1253 box.min =
V3i(x * blockSize, y * blockSize, z * blockSize);
1254 box.max = box.min +
V3i(blockSize - 1, blockSize - 1, blockSize - 1);
1259 m_currentBlockWindow = box;
1273 template <
class Data_T>
1285 template <
class Data_T>
1288 m_blockOrder(o.m_blockOrder),
1290 m_fileManager(o.m_fileManager)
1297 template <
class Data_T>
1300 if (m_fileManager) {
1304 m_fileManager->removeFieldFromCache<Data_T>(m_fileId);
1313 template <
class Data_T>
1318 this->base::operator=(o);
1326 template <
class Data_T>
1336 m_fileManager->reference<Data_T>(o.
m_fileId);
1341 setupReferenceBlocks();
1350 m_blocks =
new Block[m_numBlocks];
1351 for (
size_t i = 0; i < m_numBlocks; ++i) {
1355 1 << m_blockOrder << m_blockOrder << m_blockOrder);
1358 m_fileManager = NULL;
1364 template <
class Data_T>
1366 const std::string &layerPath,
1371 m_fileId = m_fileManager->getNextId<Data_T>(filename, layerPath);
1374 m_fileManager->reference<Data_T>(m_fileId);
1376 reference->occupiedBlocks = occupiedBlocks;
1377 reference->setNumBlocks(m_numBlocks);
1382 template <
class Data_T>
1387 for (
size_t i = 0; i < m_numBlocks; ++i) {
1390 m_blocks[i].clear();
1396 template <
class Data_T>
1399 if (!m_fileManager || m_fileId < 0)
return;
1402 m_fileManager->reference<Data_T>(m_fileId);
1406 reference->
blocks.begin();
1407 int nextBlockIdx = 0;
1408 for (
size_t i = 0; i < m_numBlocks; ++i, ++fb, ++bp) {
1409 if (m_blocks[i].isAllocated) {
1421 template <
class Data_T>
1426 Block *p = m_blocks, *end = m_blocks + m_numBlocks;
1435 template <
class Data_T>
1438 m_blockOrder = order;
1444 template <
class Data_T>
1447 return m_blockOrder;
1452 template <
class Data_T>
1455 return 1 << m_blockOrder;
1460 template <
class Data_T>
1464 applyDataWindowOffset(i, j, k);
1465 getBlockCoord(i, j, k, bi, bj, bk);
1466 return blockIsAllocated(bi, bj, bk);
1471 template <
class Data_T>
1474 const Block &block = m_blocks[blockId(bi, bj, bk)];
1480 template <
class Data_T>
1483 return m_blocks[blockId(bi, bj, bk)].emptyValue;
1488 template <
class Data_T>
1492 Block &block = m_blocks[blockId(bi, bj, bk)];
1494 deallocBlock(block, val);
1502 template <
class Data_T>
1505 return bi >= 0 && bj >= 0 && bk >= 0 &&
1506 bi < m_blockRes.x && bj < m_blockRes.y && bk < m_blockRes.z;
1511 template <
class Data_T>
1519 template <
class Data_T>
1520 template <
typename Functor_T>
1524 int numDeallocs = 0;
1532 V3i blockAllocSize(blockSize());
1534 int bx = 0, by = 0, bz = 0;
1535 for (
size_t i = 0; i < m_numBlocks; ++i, ++bx) {
1536 if (bx >= m_blockRes.x) {
1539 if (by >= m_blockRes.y) {
1544 validSize = blockAllocSize;
1545 if (bx == m_blockRes.x-1) {
1546 validSize.x = dataRes.x - bx * blockAllocSize.x;
1548 if (by == m_blockRes.y-1) {
1549 validSize.y = dataRes.y - by * blockAllocSize.y;
1551 if (bz == m_blockRes.z-1) {
1552 validSize.z = dataRes.z - bz * blockAllocSize.z;
1555 if (m_blocks[i].isAllocated) {
1556 if (func.check(m_blocks[i], emptyValue, validSize, blockAllocSize)) {
1557 deallocBlock(m_blocks[i], emptyValue);
1567 template <
class Data_T>
1570 return fastValue(i, j, k);
1575 template <
class Data_T>
1578 return fastLValue(i, j, k);
1583 template <
class Data_T>
1586 assert (i >= base::m_dataWindow.min.x);
1587 assert (i <= base::m_dataWindow.max.x);
1588 assert (j >= base::m_dataWindow.min.y);
1589 assert (j <= base::m_dataWindow.max.y);
1590 assert (k >= base::m_dataWindow.min.z);
1591 assert (k <= base::m_dataWindow.max.z);
1593 applyDataWindowOffset(i, j, k);
1596 getBlockCoord(i, j, k, bi, bj, bk);
1599 getVoxelInBlock(i, j, k, vi, vj, vk);
1601 int id = blockId(bi, bj, bk);
1602 const Block &block = m_blocks[id];
1605 if (m_fileManager) {
1606 m_fileManager->incBlockRef<Data_T>(m_fileId, id);
1607 m_fileManager->activateBlock<Data_T>(m_fileId, id);
1608 Data_T tmpValue = block.
value(vi, vj, vk, m_blockOrder);
1609 m_fileManager->decBlockRef<Data_T>(m_fileId, id);
1612 return block.
value(vi, vj, vk, m_blockOrder);
1622 template <
class Data_T>
1625 assert (i >= base::m_dataWindow.min.x);
1626 assert (i <= base::m_dataWindow.max.x);
1627 assert (j >= base::m_dataWindow.min.y);
1628 assert (j <= base::m_dataWindow.max.y);
1629 assert (k >= base::m_dataWindow.min.z);
1630 assert (k <= base::m_dataWindow.max.z);
1632 if (m_fileManager) {
1633 assert(
false &&
"Called fastLValue() on a dynamic-read sparse field");
1640 applyDataWindowOffset(i, j, k);
1643 getBlockCoord(i, j, k, bi, bj, bk);
1646 getVoxelInBlock(i, j, k, vi, vj, vk);
1648 int id = blockId(bi, bj, bk);
1649 Block &block = m_blocks[id];
1652 return block.
value(vi, vj, vk, m_blockOrder);
1655 size_t blockSize = 1 << m_blockOrder << m_blockOrder << m_blockOrder;
1657 return block.
value(vi, vj, vk, m_blockOrder);
1663 template <
class Data_T>
1666 int id = blockId(bi, bj, bk);
1667 const Block &block = m_blocks[id];
1677 template <
class Data_T>
1680 long long int blockSize = m_numBlocks *
sizeof(
Block);
1681 long long int dataSize = 0;
1683 for (
size_t i = 0; i < m_numBlocks; ++i) {
1684 if (m_blocks[i].data) {
1685 dataSize += (1 << m_blockOrder << m_blockOrder << m_blockOrder) *
1690 return sizeof(*this) + dataSize + blockSize;
1695 template <
class Data_T>
1699 const size_t blockSize = (1 << m_blockOrder << m_blockOrder << m_blockOrder);
1701 for (
size_t i = 0; i < m_numBlocks; ++i) {
1702 if (m_blocks[i].isAllocated) {
1712 template <
class Data_T>
1718 return const_iterator(*
this, base::m_dataWindow, base::m_dataWindow.min,
1724 template <
class Data_T>
1728 if (subset.isEmpty())
1729 return cend(subset);
1735 template <
class Data_T>
1740 V3i(base::m_dataWindow.min.x,
1741 base::m_dataWindow.min.y,
1742 base::m_dataWindow.max.z + 1),
1748 template <
class Data_T>
1755 subset.max.z + 1), m_blockOrder);
1760 template <
class Data_T>
1766 return iterator(*
this, base::m_dataWindow,
1767 base::m_dataWindow.min, m_blockOrder); }
1771 template <
class Data_T>
1775 if (subset.isEmpty())
1777 return iterator(*
this, subset, subset.min, m_blockOrder);
1782 template <
class Data_T>
1786 return iterator(*
this, base::m_dataWindow,
1787 V3i(base::m_dataWindow.min.x,
1788 base::m_dataWindow.min.y,
1789 base::m_dataWindow.max.z + 1), m_blockOrder);
1794 template <
class Data_T>
1799 V3i(subset.min.x, subset.min.y, subset.max.z + 1),
1805 template <
class Data_T>
1817 template <
class Data_T>
1822 V3i(0, 0, m_blockRes.z));
1827 template <
class Data_T>
1831 V3f res(base::m_dataWindow.size() +
V3i(1));
1832 V3f blockRes(res / (1 << m_blockOrder));
1833 blockRes.x =
ceil(blockRes.x);
1834 blockRes.y =
ceil(blockRes.y);
1835 blockRes.z =
ceil(blockRes.z);
1836 V3i intBlockRes(static_cast<int>(blockRes.x),
1837 static_cast<int>(blockRes.y),
1838 static_cast<int>(blockRes.z));
1839 m_blockRes = intBlockRes;
1840 m_blockXYSize = m_blockRes.x * m_blockRes.y;
1844 m_numBlocks = intBlockRes.x * intBlockRes.y * intBlockRes.z;
1845 m_blocks =
new Block[m_numBlocks];
1850 template <
class Data_T>
1853 return blockK * m_blockXYSize + blockJ * m_blockRes.x + blockI;
1859 template <
class Data_T>
1861 int &bi,
int &bj,
int &bk)
const
1866 bi = i >> m_blockOrder;
1867 bj = j >> m_blockOrder;
1868 bk = k >> m_blockOrder;
1874 template <
class Data_T>
1876 int &vi,
int &vj,
int &vk)
const
1881 vi = i & ((1 << m_blockOrder) - 1);
1882 vj = j & ((1 << m_blockOrder) - 1);
1883 vk = k & ((1 << m_blockOrder) - 1);
1888 template <
class Data_T>
1891 m_fileManager->incBlockRef<Data_T>(m_fileId, blockId);
1896 template <
class Data_T>
1899 m_fileManager->activateBlock<Data_T>(m_fileId, blockId);
1904 template <
class Data_T>
1907 m_fileManager->decBlockRef<Data_T>(m_fileId, blockId);
1912 template <
class Data_T>
1920 template <
class Data_T>
1924 const size_t blockSide = (1 << m_blockOrder);
1928 const V3i start(bCoord * blockSide + base::m_dataWindow.min);
1931 const Box3i unclipped(start, end);
1932 bounds =
clipBounds(unclipped, base::m_dataWindow);
1934 return bounds == unclipped;
1939 template <
class Data_T>
1954 #endif // Include guard
const class_type & m_field
Pointer to field we're traversing.
int m_blockOrder
Block size.
SparseField< double > SparseFieldd
#define FIELD3D_NAMESPACE_HEADER_CLOSE
V3i blockRes() const
Returns the resolution of the block array.
Box3i clipBounds(const Box3i &bbox, const Box3i &bounds)
bool isAnyLess(const Data_T &left, const Data_T &right)
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...
Box3i blockCoords(const Box3i &dvsBounds, const SparseField< Data_T > *f)
RefBase base
Convenience typedef for referring to base class.
V3i m_blockRes
Block array resolution.
size_t numGrains() const
Number of 'grains' to use with threaded access.
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...
int releaseBlocks(Functor_T func)
Releases any blocks that are deemed empty. This can be used to clean up after algorithms that write "...
Data_T & value(int i, int j, int k, int blockOrder)
Gets the value of a given voxel.
iterator begin()
Iterator to first element.
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..
bool voxelIsInAllocatedBlock(int i, int j, int k) const
Checks if a voxel is in an allocated block.
int m_fileId
File id. Used with m_fileManager if active. Otherwise -1.
const SparseBlock & operator=(const SparseBlock &)
Non-copyable.
SparseField< float > SparseFieldf
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 const char * staticClassType()
Box3i m_window
Window to traverse.
Data_T fastValue(int i, int j, int k) const
Read access to voxel. Notice that this is non-virtual.
void applyDataWindowOffset(int &i, int &j, int &k) const
Applies data window offset.
const Data_T & value(int i, int j, int k, int blockOrder) const
Gets the const value of a given voxel.
int m_blockXYSize
Block array res.x * res.y.
int blockId(int blockI, int blockJ, int blockK) const
Calculates the block number based on a block i,j,k index.
Data_T * m_p
Current pointed-to element.
bool isDynamicLoad() const
Whether the field is dynamically loaded.
block_iterator(const class_type &field, const Box3i &window, const V3i ¤tPos)
Constructor.
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.
Contains functions controlling the loading of sparse fields.
void setupReferenceBlocks()
Internal function to setup the Reference's block pointers, for use with dynamic reading.
boost::intrusive_ptr< FieldBase > Ptr
value_type sample(const SparseField< Data_T > &field, const V3d &vsP) const
int x
Current x/y/z coord.
Data_T * data
Pointer to data. Null if block is unallocated.
~SparseField()
Destructor.
FIELD3D_API void print(Severity severity, const std::string &message)
Sends the string to the assigned output, prefixing the message with the severity. ...
virtual void sizeChanged()
Subclasses should re-implement this if they need to perform memory allocations, etc. every time the size of the storage changes.
FIELD3D_VEC3_T< T > operator*(S s, const FIELD3D_VEC3_T< T > vec)
Scalar times Vec3 multiplication. Makes the interpolation calls cleaner.
int m_blockOrder
Block order (size = 2^blockOrder)
std::vector< int > fileBlockIndices
Index in file for each block.
boost::intrusive_ptr< SparseField > Ptr
Data_T value_type
Allows us to reference the template class.
int m_blockStepsTicker
Ticker for how many more steps to take before resetting the pointer.
static TemplatedFieldType< LinearSparseFieldInterp< Data_T > > ms_classType
void activateBlock(const int blockId) const
Activates a given block.
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...
void setupNextBlock(int i, int j, int k)
Convenience.
virtual Data_T & lvalue(int i, int j, int k)
Write access to a voxel. The coordinates are global coordinates.
SparseField()
Constructs an empty buffer.
SparseField< V3f > SparseField3f
SparseField< Data_T > class_type
Box3i m_dataWindow
Defines the area where data is allocated. This should be treated as a closed (i.e. inclusive) interval.
Data_T emptyValue
The value to use if the block isn't allocated. We allow setting this per block so that we for example...
SparseField< half > SparseFieldh
boost::intrusive_ptr< LinearSparseFieldInterp > Ptr
Sparse::SparseBlock< Data_T > Block
iterator end()
Iterator pointing one element past the last valid one.
static TemplatedFieldType< SparseField< Data_T > > ms_classType
FIELD3D_CLASSTYPE_TEMPL_INSTANTIATION(LinearSparseFieldInterp)
SparseField< Data_T > class_type
BlockPtrs blocks
Pointers to each block. This is so we can go in and manipulate them as we please. ...
Namespace for sparse field specifics.
void decBlockRef(const int blockId) const
Decrements the block ref count for the given block.
FIELD3D_VEC3_T< T > floor(const FIELD3D_VEC3_T< T > &v)
Floor function for Vec3.
void copySparseField(const SparseField &o)
Copies internal data, including blocks, from another SparseField, used by copy constructor and operat...
Checks if all the absolute values in the SparseBlock are greater than some number. Useful for making narrow band levelsets Used by SparseField::releaseBlocks().
virtual void clear(const Data_T &value)
Clears all the voxels in the storage.
void resize(int n)
Alloc data.
static const char * staticClassName()
const Data_T * m_p
Current pointed-to element.
bool blockIsAllocated(int bi, int bj, int bk) const
Checks if a block is allocated.
Data_T & fastLValue(int i, int j, int k)
Write access to voxel. Notice that this is non-virtual.
CheckMaxAbs(Data_T maxValue)
Constructor. Takes max value.
Box3i m_currentBlockWindow
Bounding box in voxel coordinates for the current block.
static const char * staticClassType()
virtual Data_T value(int i, int j, int k) const
Read access to a voxel. The coordinates are in integer voxel space .
Data_T m_dummy
Dummy value used when needing to return but indicating a failed call.
LinearSparseFieldInterp class_type
void recomputeBlockBoundingBox()
Box3i m_window
Bounding box for block indices.
void setBlockOrder(int order)
Sets the block order (i.e. the power-of-2 to use as block size.
bool getGrainBounds(const size_t idx, Box3i &vsBounds) const
Bounding box of the given 'grain'.
iterator(class_type &field, const Box3i &window, const V3i ¤tPos, int blockOrder)
void copy(const SparseBlock &other, size_t n)
Copy data from another block.
block_iterator blockBegin() const
int m_blockOrder
Block size.
virtual size_t voxelCount() const
Counts the number of voxels. For most fields, this is just the volume of the data window...
void setupBlocks()
Initializes the block structure. Will clear any existing data.
bool isAllocated
Whether the block is allocated or not.
Used to return a string for the name of a templated field.
V3i const dataResolution() const
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)
int x
Current block index.
Storage for one individual block of a SparseField.
SparseField< Data_T > class_type
Convenience typedef.
bool blockIndexIsValid(int bi, int bj, int bk) const
Returns whether a block index is valid.
void incBlockRef(const int blockId) const
Increments the block ref count for the given block.
Box3i m_window
Window to traverse.
LinearSparseFieldInterp< Data_T > LinearInterp
static const char * staticClassName()
Contains Field, WritableField and ResizableField classes.
bool match(const std::string &name, const std::string &attribute, const std::vector< std::string > &patterns, const MatchFlags flags=MatchEmptyPattern)
Matches a
: string against a set of patterns.
static boost::mutex ms_resizeMutex
Prevents concurrent allocation of blocks. There should be little contention, and this prevents multip...
block_iterator blockEnd() const
Const iterator pointing to element one past the last valid block.
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.
const_iterator cend() const
Const iterator pointing one element past the last valid one.
SparseField< V3d > SparseField3d
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.
void copyBlockStates(const SparseField< Data_T > &o)
Internal function to copy empty values and allocated flags, without copying data, used when copying a...
DEFINE_FIELD_RTTI_CONCRETE_CLASS
const class_type * m_field
Reference to field we're traversing.
Sparse::SparseBlock< Data_T > Block
const_iterator(const class_type &field, const Box3i &window, const V3i ¤tPos, int blockOrder)
V3i indexToCoord(const size_t idx, const V3i &res)
size_t m_numBlocks
Number of blocks in field.
CubicGenericFieldInterp< SparseField< Data_T > > CubicInterp
ResizableField< Data_T > base
SparseField & operator=(const SparseField &o)
Assignment operator. For cache-managed fields, it creates a new file reference, and for non-managed f...
bool m_isEmptyBlock
Whether we're at an empty block and we don't increment m_p.
bool m_isEmptyBlock
Whether we're at an empty block and we don't increment m_p.
int blockOrder() const
Returns the block order.
bool m_blockIsActivated
Used with delayed-load fields. Check if we've already activated the current blocks.
Sparse::SparseBlock< Data_T > Block
void deallocBlock(Block &block, const Data_T &emptyValue)
Deallocated the data of the given block and sets its empty value.
This Field subclass stores voxel data in block-allocated arrays.
FIELD3D_VEC3_T< T > ceil(const FIELD3D_VEC3_T< T > &v)
Ceil function for Vec3.
static SparseFileManager & singleton()
Returns a reference to the singleton instance.
const Box3i & dataWindow() const
Returns the data window. Any coordinate inside this window is safe to pass to value() in the Field su...
virtual void sizeChanged()
Subclasses should re-implement this if they need to perform memory allocations, etc. every time the size of the storage changes.
Checks if all the values in the SparseBlock are equal. Used by SparseField::releaseBlocks().
const Box3i & blockBoundingBox()
Returns a reference to the bounding box representing the current block.
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.
SparseField< V3h > SparseField3h
DEFINE_FIELD_RTTI_CONCRETE_CLASS
SparseField< Data_T > class_type
SparseFileManager * m_manager
Pointer to the singleton file manager.
SparseFileManager * m_fileManager
Pointer to SparseFileManager. Used when doing dynamic reading. NULL if not in use.
int m_blockStepsTicker
Ticker for how many more steps to take before resetting the pointer.
const_iterator cbegin() const
Const iterator to first element. "cbegin" matches the tr1 c++ standard.
int blockSize() const
Returns the block size.
void setupNextBlock(int i, int j, int k)
Block * m_blocks
Array of blocks. Not using std::vector since SparseBlock is noncopyable.
class_type * m_field
Reference to field we're traversing.
FIELD3D_CLASSNAME_CLASSTYPE_IMPLEMENTATION
std::string name
Optional name of the field.