Go to the documentation of this file.
44 #ifndef _INCLUDED_MIPField_H_
45 #define _INCLUDED_MIPField_H_
49 #include <boost/lexical_cast.hpp>
50 #include <boost/thread/mutex.hpp>
108 template <
class Field_T>
115 typedef typename Field_T::value_type
Data_T;
118 typedef boost::intrusive_ptr<MIPField>
Ptr;
119 typedef std::vector<Ptr>
Vec;
233 const Field_T*
rawMipLevel(
const size_t level)
const;
288 template <
typename T>
297 template <
typename Data_T>
309 template <
typename Data_T>
323 template <
class Field_T>
326 m_ioMutex(new boost::mutex)
333 template <
class Field_T>
342 template <
class Field_T>
346 base::operator=(rhs);
352 template <
class Field_T>
364 m_fields.resize(rhs.
m_fields.size());
366 for (
size_t i = 0, end = m_fields.size(); i < end; ++i) {
370 FieldPtr clone = field_dynamic_cast<Field_T>(baseClone);
374 std::cerr <<
"MIPField::op=(): Failed to clone." << std::endl;
378 m_rawFields[i] = m_fields[i].get();
381 m_ioMutex.reset(
new boost::mutex);
388 template <
class Field_T>
393 base::m_numLevels = 0;
394 base::m_lowestLevel = 0;
399 template <
class Field_T>
405 sanityChecks(fields);
408 base::m_numLevels = fields.size();
409 base::m_lowestLevel = 0;
410 updateMapping(fields[0]);
413 m_mipRes.resize(base::m_numLevels);
414 m_relativeResolution.resize(base::m_numLevels);
416 for (
size_t i = 0; i < fields.size(); i++) {
418 m_mipRes[i] = m_fields[i]->extents().size() +
V3i(1);
420 m_relativeResolution[i] =
V3f(m_mipRes[i]) / m_mipRes[0];
426 template <
class Field_T>
436 if (proxies.size() != actions.size()) {
437 throw MIPFieldException(
"Incorrect number of lazy load actions");
440 sanityChecks(proxies);
442 m_loadActions = actions;
444 base::m_numLevels = proxies.size();
445 base::m_lowestLevel = 0;
446 m_fields.resize(base::m_numLevels);
447 updateMapping(proxies[0]);
450 m_mipRes.resize(base::m_numLevels);
451 m_relativeResolution.resize(base::m_numLevels);
452 for (
size_t i = 0; i < proxies.size(); i++) {
454 m_mipRes[i] = proxies[i]->extents().size() +
V3i(1);
456 m_relativeResolution[i] =
V3f(m_mipRes[i]) / m_mipRes[0];
464 template <
class Field_T>
468 assert(level < base::m_numLevels);
470 if (!m_rawFields[level]) {
471 loadLevelFromDisk(level);
473 return m_fields[level];
479 template <
class Field_T>
483 assert(level < base::m_numLevels);
485 if (!m_rawFields[level]) {
486 loadLevelFromDisk(level);
489 return m_rawFields[level];
494 template <
class Field_T>
495 typename Field_T::Ptr
498 assert(level < base::m_numLevels);
500 if (!m_rawFields[level]) {
501 loadLevelFromDisk(level);
504 return m_fields[level];
509 template <
class Field_T>
513 return fastMipValue(0, i, j, k);
518 template <
class Field_T>
523 for (
size_t i = 0; i < m_fields.size(); i++) {
525 count += m_fields[i]->voxelCount();
533 template <
class Field_T>
536 long long int mem = 0;
537 for (
size_t i = 0; i < m_fields.size(); i++) {
539 mem += m_fields[i]->memSize();
542 return mem +
sizeof(*this);
547 template <
class Field_T>
553 base::setMIPOffset(offset);
555 V3i baseRes = base::dataWindow().size() +
V3i(1);
557 m_fields[0]->setMapping(base::mapping());
559 for (
size_t i = 1; i < m_fields.size(); i++) {
563 m_fields[i]->extents(), i);
564 m_fields[i]->setMapping(mapping);
571 template <
class Field_T>
575 return fastMipValue(level, i, j, k);
580 template <
class Field_T>
583 assert(level < base::m_numLevels);
584 return m_mipRes[level];
589 template <
class Field_T>
592 assert(level < base::m_numLevels);
593 return m_rawFields[level] != NULL;
598 template <
typename Field_T>
602 const V3i &mipOff = base::mipOffset();
605 const V3i offset((mipOff.x >> level) << level,
606 (mipOff.y >> level) << level,
607 (mipOff.z >> level) << level);
611 const V3f diff = offset - mipOff;
614 outVsP = (vsP - diff) * pow(2.0, -
static_cast<float>(level));
619 template <
typename Field_T>
623 assert(level < base::m_numLevels);
625 if (!m_rawFields[level]) {
626 loadLevelFromDisk(level);
629 return m_fields[level];
634 template <
class Field_T>
638 assert(level < base::m_numLevels);
640 if (!m_rawFields[level]) {
641 loadLevelFromDisk(level);
644 return m_rawFields[level]->fastValue(i, j, k);
649 template <
class Field_T>
652 m_rawFields.resize(m_fields.size());
653 for (
size_t i = 0; i < m_fields.size(); i++) {
654 m_rawFields[i] = m_fields[i].get();
660 template <
class Field_T>
666 m_fields[level]->name = base::name;
667 m_fields[level]->attribute = base::attribute;
669 m_fields[level]->copyMetadata(*
this);
674 template <
class Field_T>
677 base::m_extents = field->extents();
678 base::m_dataWindow = field->dataWindow();
679 base::setMapping(field->mapping());
684 template <
class Field_T>
688 if (!m_rawFields[level]) {
689 boost::mutex::scoped_lock lock(*m_ioMutex);
690 if (!m_rawFields[level]) {
692 m_fields[level] = m_loadActions[level]->load();
694 if (!m_fields[level]) {
695 throw Exc::MIPFieldException(
"Couldn't load MIP level: " +
696 boost::lexical_cast<std::string>(level));
699 m_loadActions[level].reset();
703 syncLevelInfo(level);
705 V3i baseRes = base::dataWindow().size() +
V3i(1);
708 m_fields[level]->extents(), level);
709 m_fields[level]->setMapping(mapping);
716 template <
class Field_T>
721 using boost::lexical_cast;
723 using Exc::MIPFieldException;
726 if (fields.size() == 0) {
727 throw MIPFieldException(
"Zero fields in input");
730 for (
size_t i = 0; i < fields.size(); i++) {
732 throw MIPFieldException(
"Found null pointer in input");
736 V3i prevSize = fields[0]->extents().size();
737 for (
size_t i = 1; i < fields.size(); i++) {
738 V3i size = fields[i]->extents().size();
739 if (size.x > prevSize.x ||
740 size.y > prevSize.y ||
741 size.z > prevSize.z) {
742 throw MIPFieldException(
"Field " + lexical_cast<string>(i) +
743 " had greater resolution than previous"
746 if (size.x >= prevSize.x &&
747 size.y >= prevSize.y &&
748 size.z >= prevSize.z) {
749 throw MIPFieldException(
"Field " + lexical_cast<string>(i) +
750 " did not decrease in resolution from "
751 " previous level: " +
752 lexical_cast<string>(size) +
" > " +
753 lexical_cast<string>(prevSize));
764 template <
typename Field_T>
774 #endif // Include guard
#define FIELD3D_NAMESPACE_HEADER_CLOSE
#define DEFINE_FIELD_RTTI_CONCRETE_CLASS
boost::intrusive_ptr< MIPField > Ptr
MIPField(const MIPField &other)
Copy constructor. We need this because a) we own a mutex and b) we own shared pointers and shallow co...
boost::intrusive_ptr< Field > Ptr
const MIPField & operator=(const MIPField &rhs)
Assignment operator.
CubicMIPFieldInterp< Data_T > CubicInterp
void setupLazyLoad(const ProxyVec &proxies, const typename LazyLoadAction< Field_T >::Vec &actions)
Sets up the MIP field in lazy-load mode.
virtual void mappingChanged()
We need to know if the mapping changed so that we may update the MIP levels' mappings.
EmptyField< Data_T > ProxyField
static DEFINE_FIELD_RTTI_CONCRETE_CLASS const char * staticClassName()
LazyLoadAction< Field_T >::Vec m_loadActions
Lazy load actions. Only used if setupLazyLoad() has been called.
virtual FieldBase::Ptr clone() const
Returns a pointer to a copy of the field, pure virtual so ensure derived classes properly implement i...
std::vector< Field_T * > m_rawFields
Raw pointers to MIP levels.
boost::intrusive_ptr< FieldMapping > Ptr
boost::intrusive_ptr< EmptyField > Ptr
Data_T fastMipValue(size_t level, int i, int j, int k) const
Read access to voxel at a given MIP level.
virtual FieldBase::Ptr clone() const
Returns a pointer to a copy of the field, pure virtual so ensure derived classes properly implement i...
std::string name
Optional name of the field.
void clear()
Clears all the levels of the MIP field.
virtual Data_T mipValue(size_t level, int i, int j, int k) const
Read access to a voxel in a given MIP level.
boost::intrusive_ptr< FieldBase > Ptr
Field_T::value_type Data_T
const Field_T * rawMipLevel(const size_t level) const
Returns a raw pointer to a MIP level.
virtual size_t voxelCount() const
Counts the number of voxels. For most fields, this is just the volume of the data window,...
boost::intrusive_ptr< FieldRes > Ptr
virtual FieldBase::Ptr clone() const
Returns a pointer to a copy of the field, pure virtual so ensure derived classes properly implement i...
MIPField()
Constructs an empty MIP field.
FIELD3D_API const std::string k_mipOffsetStr
void setup(const FieldVec &fields)
Sets up the MIP field given a set of non-MIP fields This call performs sanity checking to ensure that...
boost::shared_ptr< boost::mutex > m_ioMutex
Mutex lock around IO. Used to make sure only one thread reads MIP level data at a time....
std::vector< V3i > m_mipRes
Resolution of each MIP level.
virtual long long int memSize() const
Returns the memory usage (in bytes)
const MIPField & init(const MIPField &rhs)
Copies from a second MIPField.
virtual Data_T value(int i, int j, int k) const
Read access to a voxel. The coordinates are in integer voxel space .
size_t m_numLevels
Number of MIP levels. The default is 1.
void updateMapping(FieldRes::Ptr field)
Updates the mapping, extents and data window to match the given field. Used so that the MIPField will...
FIELD3D_CLASSNAME_CLASSTYPE_IMPLEMENTATION
virtual Field< Data_T >::Ptr mipLevel(const size_t level) const
Returns a MIP level field.
This subclass of Field does not store any data.
void sanityChecks(const T &fields)
Sanity checks to ensure that the provided Fields are a MIP representation.
Contains the DenseField class.
Namespace for Exception objects.
void updateAuxMembers() const
Updates the dependent data members based on m_field.
Contains MIPInterp class.
void loadLevelFromDisk(size_t level) const
Loads the given level from disk.
virtual void getVsMIPCoord(const V3f &vsP, const size_t level, V3f &outVsP) const
Given a voxel space coordinate in the 0-level field, computes the coordinate in another level.
This subclass stores a MIP representation of a Field_T field.
Used to return a string for the name of a nested templated field.
Contains the EmptyField class.
static const char * staticClassType()
std::vector< V3f > m_relativeResolution
Relative resolution of each MIP level. Pre-computed to avoid int-to-float conversions.
FIELD3D_API FieldMapping::Ptr adjustedMIPFieldMapping(const FieldRes *base, const V3i &baseRes, const Box3i &extents, const size_t level)
Field_T::Ptr concreteMipLevel(const size_t level) const
Returns a concretely typed pointer to a MIP level.
std::vector< FieldPtr > FieldVec
void syncLevelInfo(const size_t level) const
Updates the name, attribute and metadata for a given level.
Contains the SparseField class.
std::vector< ProxyPtr > ProxyVec
Contains MIP-related utility functions.
virtual V3i mipResolution(size_t level) const
Returns the resolution of a given MIP level.
virtual bool levelLoaded(const size_t level) const
Whether a given MIP level is loaded.
std::vector< FieldPtr > m_fields
Storage of all MIP levels. Some or all of the pointers may be NULL. This is mutable because it needs ...
#define DECLARE_FIELD3D_GENERIC_EXCEPTION(name, base_class)
Used to declare a generic but named exception.
MIPField< Field_T > class_type
MIPLinearInterp< MIPField< Field_T > > LinearInterp
static NestedFieldType< MIPField< Field_T > > ms_classType