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));
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))));
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];
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>
442 int blockId(
int blockI,
int blockJ,
int blockK)
const;
487 virtual Data_T
value(
int i,
int j,
int k)
const;
496 virtual Data_T&
lvalue(
int i,
int j,
int k);
528 class const_iterator;
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>
683 Box3i dovsBounds = dvsBounds;
693 f->
getBlockCoord(dovsBounds.min.x, dovsBounds.min.y, dovsBounds.min.z,
694 dbsBounds.min.x, dbsBounds.min.y, dbsBounds.min.z);
695 f->
getBlockCoord(dovsBounds.max.x, dovsBounds.max.y, dovsBounds.max.z,
696 dbsBounds.max.x, dbsBounds.max.y, dbsBounds.max.z);
709template <
typename Data_T>
721 const V3i &validSize,
const V3i &blockSize)
724 Data_T first = block.
data[0];
727 size_t len = blockSize.x * blockSize.y * blockSize.z;
728 if (validSize == blockSize) {
730 for (
size_t i = 0; i < len; i++) {
731 if (block.
data[i] != first) {
739 for (
size_t i = 0; i < len; i++, x++) {
740 if (x >= blockSize.x) {
743 if (y >= blockSize.y) {
748 if (x >= validSize.x || y >= validSize.y || z >= validSize.z) {
751 if (block.
data[i] != first) {
759 retEmptyValue = first;
769template <
typename Data_T>
770inline bool isAnyLess(
const Data_T &left,
const Data_T &right)
772 return (std::abs(left) < right);
780 return (std::abs(left.x) < right.x ||
781 std::abs(left.y) < right.y ||
782 std::abs(left.z) < right.z );
790 return (std::abs(left.x) < right.x ||
791 std::abs(left.y) < right.y ||
792 std::abs(left.z) < right.z );
800 return (std::abs(left.x) < right.x ||
801 std::abs(left.y) < right.y ||
802 std::abs(left.z) < right.z );
810template <
typename Data_T>
826 const V3i &validSize,
const V3i &blockSize)
829 Data_T first = block.
data[0];
831 bool allGreater =
true;
832 size_t len = blockSize.x * blockSize.y * blockSize.z;
834 if (validSize == blockSize) {
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) {
854 if (x >= validSize.x || y >= validSize.y || z >= validSize.z) {
865 retEmptyValue = first;
884template <
class Data_T>
888#if defined(WIN32) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
889 typedef std::forward_iterator_tag iterator_category;
891 typedef ptrdiff_t difference_type;
892 typedef ptrdiff_t distance_type;
893 typedef Data_T *pointer;
894 typedef Data_T& reference;
901 :
x(currentPos.
x),
y(currentPos.
y),
z(currentPos.
z),
918 bool resetPtr =
false;
949 template <
class Iter_T>
950 inline bool operator == (
const Iter_T &rhs)
const
952 return x == rhs.x &&
y == rhs.y &&
z == rhs.z;
954 template <
class Iter_T>
955 inline bool operator != (
const Iter_T &rhs)
const
957 return x != rhs.x ||
y != rhs.y ||
z != rhs.z;
966 m_field->getVoxelInBlock(
x,
y,
z, vi, vj, vk);
971 inline const Data_T* operator -> ()
const
979 m_field->getVoxelInBlock(
x,
y,
z, vi, vj, vk);
1000 m_field->applyDataWindowOffset(i, j, k);
1006 oldBlockId <
static_cast<int>(
m_field->m_numBlocks) &&
1007 m_field->m_blocks[oldBlockId].isAllocated) {
1017 m_field->getVoxelInBlock(i, j, k, vi, vj, vk);
1066template <
class Data_T>
1070#if defined(WIN32) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
1071 typedef std::forward_iterator_tag iterator_category;
1073 typedef ptrdiff_t difference_type;
1074 typedef ptrdiff_t distance_type;
1075 typedef Data_T *pointer;
1076 typedef Data_T& reference;
1081 const Box3i &window,
1083 :
x(currentPos.
x),
y(currentPos.
y),
z(currentPos.
z),
1091 bool resetPtr =
false;
1124 return x == rhs.
x &&
y == rhs.
y &&
z == rhs.
z;
1128 return x != rhs.
x ||
y != rhs.
y ||
z != rhs.
z;
1133 assert(
false &&
"Dereferencing iterator on a dynamic-read sparse field");
1147 inline Data_T* operator -> ()
1150 assert(
false &&
"Dereferencing iterator on a dynamic-read sparse field");
1171 m_field->applyDataWindowOffset(i, j, k);
1180 m_field->getVoxelInBlock(i, j, k, vi, vj, vk);
1212template <
class Data_T>
1220 const V3i ¤tPos)
1221 :
x(currentPos.
x),
y(currentPos.
y),
z(currentPos.
z),
1247 return x == rhs.
x &&
y == rhs.
y &&
z == rhs.
z;
1252 return x != rhs.
x ||
y != rhs.
y ||
z != rhs.
z;
1286template <
class Data_T>
1298template <
class Data_T>
1310template <
class Data_T>
1326template <
class Data_T>
1339template <
class Data_T>
1378template <
class Data_T>
1380 const std::string &layerPath,
1390 reference->valuesPerBlock = valuesPerBlock;
1391 reference->numVoxels = numVoxels;
1392 reference->occupiedBlocks = occupiedBlocks;
1398template <
class Data_T>
1412template <
class Data_T>
1420#if F3D_NO_BLOCKS_ARRAY
1423 int nextBlockIdx = 0;
1435 reference->
blocks.begin();
1436 int nextBlockIdx = 0;
1437 for (
size_t i = 0; i <
m_numBlocks; ++i, ++fb, ++bp) {
1451template <
class Data_T>
1465template <
class Data_T>
1474template <
class Data_T>
1482template <
class Data_T>
1490template <
class Data_T>
1501template <
class Data_T>
1510template <
class Data_T>
1518template <
class Data_T>
1532template <
class Data_T>
1535 return bi >= 0 && bj >= 0 && bk >= 0 &&
1541template <
class Data_T>
1549template <
class Data_T>
1550template <
typename Functor_T>
1554 int numDeallocs = 0;
1564 int bx = 0, by = 0, bz = 0;
1574 validSize = blockAllocSize;
1576 validSize.x = dataRes.x - bx * blockAllocSize.x;
1579 validSize.y = dataRes.y - by * blockAllocSize.y;
1582 validSize.z = dataRes.z - bz * blockAllocSize.z;
1586 if (func.check(
m_blocks[i], emptyValue, validSize, blockAllocSize)) {
1597template <
class Data_T>
1605template <
class Data_T>
1613template <
class Data_T>
1652template <
class Data_T>
1663 assert(
false &&
"Called fastLValue() on a dynamic-read sparse field");
1693template <
class Data_T>
1707template <
class Data_T>
1711 long long int dataSize = 0;
1720 return sizeof(*this) + dataSize +
blockSize;
1725template <
class Data_T>
1742template <
class Data_T>
1754template <
class Data_T>
1758 if (subset.isEmpty())
1759 return cend(subset);
1765template <
class Data_T>
1778template <
class Data_T>
1790template <
class Data_T>
1801template <
class Data_T>
1805 if (subset.isEmpty())
1812template <
class Data_T>
1824template <
class Data_T>
1829 V3i(subset.min.x, subset.min.y, subset.max.z + 1),
1835template <
class Data_T>
1847template <
class Data_T>
1857template <
class Data_T>
1874 m_numBlocks = intBlockRes.x * intBlockRes.y * intBlockRes.z;
1880template <
class Data_T>
1889template <
class Data_T>
1891 int &bi,
int &bj,
int &bk)
const
1904template <
class Data_T>
1906 int &vi,
int &vj,
int &vk)
const
1918template <
class Data_T>
1926template <
class Data_T>
1934template <
class Data_T>
1942template <
class Data_T>
1950template <
class Data_T>
1959 const V3i end (start + Imath::V3i(blockSide - 1));
1964 return bounds == unclipped;
1969template <
class Data_T>
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
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()
RefBase & operator=(const RefBase &)
Assignment operator.
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.
SparseField(const SparseField &o)
Copy constructor.
Sparse::SparseBlock< Data_T > Block
virtual void sizeChanged()
Subclasses should re-implement this if they need to perform memory allocations, etc....
SparseFileManager * m_fileManager
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.
iterator begin(const Box3i &subset)
Iterator to first element of specific subset.
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
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.
bool blockIndexIsValid(int bi, int bj, int bk) const
Returns whether a block index is valid.
ResizableField< Data_T > base
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()
~SparseField()
Destructor.
SparseField()
Constructs an empty buffer.
SparseField< Data_T > class_type
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.
const_iterator cend(const Box3i &subset) const
Const iterator pointing one element past the last valid one (for a subset)
Data_T & fastLValue(int i, int j, int k)
Write access to voxel. Notice that this is non-virtual.
const_iterator cbegin(const Box3i &subset) const
Const iterator to first element of specific subset.
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.
iterator end(const Box3i &subset)
Iterator pointing one element past the last valid one (for a subset)
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.
virtual size_t voxelCount() const
Counts the number of voxels. For most fields, this is just the volume of the data window,...
virtual half value(int i, int j, int k) const
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...
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.
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 & value(int i, int j, int k, int blockOrder)
Gets the value of a given voxel.
static boost::mutex ms_resizeMutex
Used to return a string for the name of a templated field.