44#ifndef _INCLUDED_MIPField_H_
45#define _INCLUDED_MIPField_H_
49#include <boost/lexical_cast.hpp>
50#include <boost/thread/mutex.hpp>
108template <
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;
288 template <
typename T>
297template <
typename Data_T>
309template <
typename Data_T>
323template <
class Field_T>
326 m_ioMutex(new boost::mutex)
333template <
class Field_T>
342template <
class Field_T>
346 base::operator=(rhs);
352template <
class Field_T>
364 m_fields.resize(rhs.
m_fields.size());
366 for (
size_t i = 0, end = m_fields.size(); i < end; ++i) {
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);
388template <
class Field_T>
393 base::m_numLevels = 0;
394 base::m_lowestLevel = 0;
399template <
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];
426template <
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];
464template <
class Field_T>
468 assert(level < base::m_numLevels);
470 if (!m_rawFields[level]) {
471 loadLevelFromDisk(level);
473 return m_fields[level];
479template <
class Field_T>
483 assert(level < base::m_numLevels);
485 if (!m_rawFields[level]) {
486 loadLevelFromDisk(level);
489 return m_rawFields[level];
494template <
class Field_T>
498 assert(level < base::m_numLevels);
500 if (!m_rawFields[level]) {
501 loadLevelFromDisk(level);
504 return m_fields[level];
509template <
class Field_T>
513 return fastMipValue(0, i, j, k);
518template <
class Field_T>
523 for (
size_t i = 0; i < m_fields.size(); i++) {
525 count += m_fields[i]->voxelCount();
533template <
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);
547template <
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);
571template <
class Field_T>
575 return fastMipValue(level, i, j, k);
580template <
class Field_T>
583 assert(level < base::m_numLevels);
584 return m_mipRes[level];
589template <
class Field_T>
592 assert(level < base::m_numLevels);
593 return m_rawFields[level] != NULL;
598template <
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));
619template <
typename Field_T>
623 assert(level < base::m_numLevels);
625 if (!m_rawFields[level]) {
626 loadLevelFromDisk(level);
629 return m_fields[level];
634template <
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);
649template <
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();
660template <
class Field_T>
666 m_fields[level]->name = base::name;
667 m_fields[level]->attribute = base::attribute;
669 m_fields[level]->copyMetadata(*
this);
674template <
class Field_T>
677 base::m_extents = field->extents();
678 base::m_dataWindow = field->dataWindow();
679 base::setMapping(field->mapping());
684template <
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);
716template <
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));
764template <
typename Field_T>
Contains the DenseField class.
Contains the EmptyField class.
#define DECLARE_FIELD3D_GENERIC_EXCEPTION(name, base_class)
Used to declare a generic but named exception.
Contains MIPInterp class.
Contains MIP-related utility functions.
#define DEFINE_FIELD_RTTI_CONCRETE_CLASS
Contains the SparseField class.
This subclass of Field does not store any data.
boost::intrusive_ptr< EmptyField > Ptr
boost::intrusive_ptr< FieldBase > Ptr
std::string name
Optional name of the field.
boost::intrusive_ptr< FieldMapping > Ptr
boost::intrusive_ptr< FieldRes > Ptr
boost::intrusive_ptr< Field > Ptr
size_t m_numLevels
Number of MIP levels. The default is 1.
virtual FieldBase::Ptr clone() const
Returns a pointer to a copy of the field, pure virtual so ensure derived classes properly implement i...
This subclass stores a MIP representation of a Field_T field.
const Field_T * rawMipLevel(const size_t level) const
Returns a raw pointer to a MIP level.
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....
virtual Data_T mipValue(size_t level, int i, int j, int k) const
Read access to a voxel in a given MIP level.
void syncLevelInfo(const size_t level) const
Updates the name, attribute and metadata for a given level.
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.
static NestedFieldType< MIPField< Field_T > > ms_classType
virtual bool levelLoaded(const size_t level) const
Whether a given MIP level is loaded.
MIPField()
Constructs an empty MIP field.
void updateMapping(FieldRes::Ptr field)
Updates the mapping, extents and data window to match the given field. Used so that the MIPField will...
std::vector< FieldPtr > FieldVec
virtual long long int memSize() const
Returns the memory usage (in bytes)
static DEFINE_FIELD_RTTI_CONCRETE_CLASS const char * staticClassName()
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...
virtual Field< Data_T >::Ptr mipLevel(const size_t level) const
Returns a MIP level field.
boost::intrusive_ptr< MIPField > Ptr
std::vector< ProxyPtr > ProxyVec
EmptyField< Data_T > ProxyField
void loadLevelFromDisk(size_t level) const
Loads the given level from disk.
virtual void mappingChanged()
We need to know if the mapping changed so that we may update the MIP levels' mappings.
Field_T::value_type Data_T
Field_T::Ptr concreteMipLevel(const size_t level) const
Returns a concretely typed pointer to a MIP level.
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...
virtual size_t voxelCount() const
Counts the number of voxels. For most fields, this is just the volume of the data window,...
void clear()
Clears all the levels of the MIP field.
FIELD3D_CLASSNAME_CLASSTYPE_IMPLEMENTATION
virtual V3i mipResolution(size_t level) const
Returns the resolution of a given MIP level.
void setupLazyLoad(const ProxyVec &proxies, const typename LazyLoadAction< Field_T >::Vec &actions)
Sets up the MIP field in lazy-load mode.
void updateAuxMembers() const
Updates the dependent data members based on m_field.
std::vector< V3i > m_mipRes
Resolution of each MIP level.
virtual Data_T value(int i, int j, int k) const
Read access to a voxel. The coordinates are in integer voxel space .
void sanityChecks(const T &fields)
Sanity checks to ensure that the provided Fields are a MIP representation.
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 ...
MIPField< Field_T > class_type
const MIPField & init(const MIPField &rhs)
Copies from a second MIPField.
static const char * staticClassType()
CubicMIPFieldInterp< Data_T > CubicInterp
MIPField(const MIPField &other)
Copy constructor. We need this because a) we own a mutex and b) we own shared pointers and shallow co...
LazyLoadAction< Field_T >::Vec m_loadActions
Lazy load actions. Only used if setupLazyLoad() has been called.
MIPLinearInterp< MIPField< Field_T > > LinearInterp
std::vector< Field_T * > m_rawFields
Raw pointers to MIP levels.
const MIPField & operator=(const MIPField &rhs)
Assignment operator.
std::vector< V3f > m_relativeResolution
Relative resolution of each MIP level. Pre-computed to avoid int-to-float conversions.
virtual FieldBase::Ptr clone() const
Returns a pointer to a copy of the field, pure virtual so ensure derived classes properly implement i...
Field_T::Ptr field_dynamic_cast(RefBase::Ptr field)
Dynamic cast that uses string-comparison in order to be safe even after an object crosses a shared li...
Namespace for Exception objects.
const std::string k_mipOffsetStr
FIELD3D_API FieldMapping::Ptr adjustedMIPFieldMapping(const FieldRes *base, const V3i &baseRes, const Box3i &extents, const size_t level)
#define FIELD3D_NAMESPACE_HEADER_CLOSE
Used to return a string for the name of a nested templated field.