/*======================================================================================

	Program:		Range Imaging Toolkit (RITK)
	Module:			ritkRImage.txx
	Version:		$Revision: 2388 $
	Date:			$Date: 2012-01-16 13:18:02 +0100 (Mo, 16 Jan 2012) $

	Copyright (c) 2010-2011
	Pattern Recognition Lab, 
    University Erlangen-Nuremberg, Germany
    All rights reserved.

	This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
	See RITKCopyright.txt for more information.

	http://www5.informatik.uni-erlangen.de/research/software/ritk

========================================================================================*/


#include "ritkRImage.h"
#include "ritkGenericImportImageContainer.h"
#include "ritkImagePayloadContainer.h"

namespace ritk
{

//----------------------------------------------------------------------------
template<class TRealType, unsigned int NDimension>
RImage<TRealType, NDimension>
::RImage()
{
	// Default hash: no payloads
	m_PayloadHash = 0;

	// Append the range payload to the internal payload vector
	AppendImagePayloadContainerMacro(m_RangeDataPayloadIdx, RangeImageType, RangeImageType::New(), "RangeData");

	// Append the range payload to the internal payload vector
	AppendImagePayloadContainerMacro(m_WorldCoordDataPayloadIdx, WorldCoordImageType, WorldCoordImageType::New(), "WorldCoordData");

	// Append the range payload to the internal payload vector
	AppendImagePayloadContainerMacro(m_FlagDataPayloadIdx, FlagImageType, FlagImageType::New(), "FlagData");

	// Initialize the range to world coord filter
	m_R2WCFilter = R2WCFilterType::New();

	// By default no distortion is calculated
	m_UseDistortion = false;
}


//----------------------------------------------------------------------------
template<class TRealType, unsigned int NDimension>
RImage<TRealType, NDimension>
::~RImage()
{
}


//----------------------------------------------------------------------------
template<class TRealType, unsigned int NDimension>
typename RImage<TRealType, NDimension>::HashType
RImage<TRealType, NDimension>
::GetPayloadHash() const
{
	return m_PayloadHash;
}


//----------------------------------------------------------------------------
template<class TRealType, unsigned int NDimension>
void
RImage<TRealType, NDimension>
::ComputePayloadHash()
{
	// ================================================================================= //
	// Create an integer hash from the string representation based on the djb2 algorithm //
	// See http://www.cse.yorku.ca/~oz/hash.html										 //
	// ================================================================================= //

	// Hash creation
	HashType Hash = 5381;
	int c = m_PayloadContainers.size();
	const char *str = NULL;
	Hash = ((Hash << 5) + Hash) + c;
	for ( unsigned int i = 0; i < m_PayloadContainers.size(); i++ )
	{
		str = m_PayloadContainers[i]->GetIdentifier().c_str();
			while ( (c = (*str++)) )
				Hash = ((Hash << 5) + Hash) + c;
	}

	// Update our member
	m_PayloadHash = Hash;
}


//----------------------------------------------------------------------------
template<class TRealType, unsigned int NDimension>
unsigned int
RImage<TRealType, NDimension>
::GetNumberOfPayloads() const
{
	return m_PayloadContainers.size();
}


//----------------------------------------------------------------------------
template<class TRealType, unsigned int NDimension>
unsigned int
RImage<TRealType, NDimension>
::GetNumberOfValidPayloads() const
{
	unsigned int Result = 0;
	for ( unsigned int i = 0; i < m_PayloadContainers.size(); i++ )
		if ( m_PayloadContainers[i]->GetPayload() )
			Result++;
	return Result;
}


//----------------------------------------------------------------------------
template<class TRealType, unsigned int NDimension>
void
RImage<TRealType, NDimension>
::SetPayloadContainer(GenericPayloadContainer *Payload, unsigned int idx)
{
	if ( idx >= m_PayloadContainers.size() )
	{
		m_PayloadContainers.resize(m_PayloadContainers.size()+1);
	}
	m_PayloadContainers[idx] = Payload;
}


//----------------------------------------------------------------------------
template<class TRealType, unsigned int NDimension>
unsigned int
RImage<TRealType, NDimension>
::AppendPayloadContainer(GenericPayloadContainer *Payload)
{
	// Append the payload
	m_PayloadContainers.push_back(Payload);

	// Compute the hash
	ComputePayloadHash();

	// Return the index
	return m_PayloadContainers.size()-1;
}


//----------------------------------------------------------------------------
template<class TRealType, unsigned int NDimension>
typename RImage<TRealType, NDimension>::GenericPayloadContainerPointer
RImage<TRealType, NDimension>
::GetPayloadContainer(unsigned int idx)
{
	if ( idx >= m_PayloadContainers.size() )
		itkExceptionMacro(<<"Invalid payload idx requested: " << idx << " (max=" << m_PayloadContainers.size()-1 << ")");
	return m_PayloadContainers[idx];
}


//----------------------------------------------------------------------------
template<class TRealType, unsigned int NDimension>
typename RImage<TRealType, NDimension>::GenericPayloadContainerConstPointer
RImage<TRealType, NDimension>
::GetPayloadContainer(unsigned int idx) const
{
	if ( idx >= m_PayloadContainers.size() )
		itkExceptionMacro(<<"Invalid payload idx requested: " << idx << " (max=" << m_PayloadContainers.size()-1 << ")");
	return (const GenericPayloadContainerType*)m_PayloadContainers[idx];
}


//----------------------------------------------------------------------------
template<class TRealType, unsigned int NDimension>
void
RImage<TRealType, NDimension>
::Modified() const
{
	this->GetRangeImage()->Modified();
	this->GetWorldCoordImage()->Modified();
	this->GetFlagImage()->Modified();
}


//----------------------------------------------------------------------------
template<class TRealType, unsigned int NDimension>
void
RImage<TRealType, NDimension>
::SetRegions(RegionType region)
{
	SetLargestPossibleRegion(region);
	SetBufferedRegion(region);
	SetRequestedRegion(region);
}


//----------------------------------------------------------------------------
template<class TRealType, unsigned int NDimension>
void
RImage<TRealType, NDimension>
::SetRegions(SizeType size)
{
	RegionType region; 
	region.SetSize(size);
	SetRegions(region);
}


//----------------------------------------------------------------------------
template<class TRealType, unsigned int NDimension>
void
RImage<TRealType, NDimension>
::SetLargestPossibleRegion(const RegionType &Region)
{
	// Update the superclass
	Superclass::SetLargestPossibleRegion(Region);

	// Update the camera parameters
	m_CameraParameters[CameraParameters::SX] = Region.GetSize()[0];
	m_CameraParameters[CameraParameters::SY] = Region.GetSize()[1];

}


//----------------------------------------------------------------------------
template<class TRealType, unsigned int NDimension>
void
RImage<TRealType, NDimension>
::SetRequestedRegion(const RegionType &Region)
{
	// Update the superclass
	Superclass::SetRequestedRegion(Region);

	// Update the camera parameters
	m_CameraParameters[CameraParameters::SX] = Region.GetSize()[0];
	m_CameraParameters[CameraParameters::SY] = Region.GetSize()[1];

	// Update the payload
	this->GetRangeImage()->SetRequestedRegion(Region);
	this->GetWorldCoordImage()->SetRequestedRegion(Region);
	this->GetFlagImage()->SetRequestedRegion(Region);
}


//----------------------------------------------------------------------------
template<class TRealType, unsigned int NDimension>
void
RImage<TRealType, NDimension>
::SetBufferedRegion(const RegionType &Region)
{
	// Update the superclass
	Superclass::SetBufferedRegion(Region);

	// Update the camera parameters
	m_CameraParameters[CameraParameters::SX] = Region.GetSize()[0];
	m_CameraParameters[CameraParameters::SY] = Region.GetSize()[1];
	
	// Update the payload
	this->GetRangeImage()->SetBufferedRegion(Region);
	this->GetWorldCoordImage()->SetBufferedRegion(Region);
	this->GetFlagImage()->SetBufferedRegion(Region);
}


//----------------------------------------------------------------------------
template<class TRealType, unsigned int NDimension>
void
RImage<TRealType, NDimension>
::Allocate()
{
	// Note that we do not allocate the world coord image due to performance reasons!
	this->GetRangeImage()->Allocate();
	this->GetFlagImage()->Allocate();

	//this->GetWorldCoordImage->Allocate();
}


//----------------------------------------------------------------------------
template<class TRealType, unsigned int NDimension>
void
RImage<TRealType, NDimension>
::SetSpacing(const SpacingType &Spacing)
{
	// Update the superclass
	Superclass::SetSpacing(Spacing);

	// Update the payload
	this->GetRangeImage()->SetSpacing(Spacing);
	this->GetWorldCoordImage()->SetSpacing(Spacing);
	this->GetFlagImage()->SetSpacing(Spacing);
}


//----------------------------------------------------------------------------
template<class TRealType, unsigned int NDimension>
void
RImage<TRealType, NDimension>
::SetSpacing(const double Spacing[ImageDimension] )
{
	SpacingType s(Spacing);
	this->SetSpacing(s);
}


//----------------------------------------------------------------------------
template<class TRealType, unsigned int NDimension>
void
RImage<TRealType, NDimension>
::SetSpacing(const float Spacing[ImageDimension] )
{
	itk::Vector<float, ImageDimension> sf(Spacing);
	SpacingType s;
	s.CastFrom(sf);
	this->SetSpacing(s);
}


//----------------------------------------------------------------------------
template<class TRealType, unsigned int NDimension>
void
RImage<TRealType, NDimension>
::SetOrigin(const PointType &Origin)
{
	// Update the superclass
	Superclass::SetOrigin(Origin);

	// Update the payload
	this->GetRangeImage()->SetOrigin(Origin);
	this->GetWorldCoordImage()->SetOrigin(Origin);
	this->GetFlagImage()->SetOrigin(Origin);
}


//----------------------------------------------------------------------------
template<class TRealType, unsigned int NDimension>
void
RImage<TRealType, NDimension>
::SetOrigin(const double Origin[ImageDimension])
{
	PointType p(Origin);
	this->SetOrigin(p);
}


//----------------------------------------------------------------------------
template<class TRealType, unsigned int NDimension>
void
RImage<TRealType, NDimension>
::SetOrigin(const float Origin[ImageDimension])
{
	itk::Point<float, ImageDimension> of(Origin);
	PointType p;
	p.CastFrom(of);
	this->SetOrigin(p);
}


//----------------------------------------------------------------------------
template<class TRealType, unsigned int NDimension>
void
RImage<TRealType, NDimension>
::SetDirection(const DirectionType Direction)
{
	// Update the superclass
	Superclass::SetDirection(Direction);

	// Update the payload
	this->GetRangeImage()->SetDirection(Direction);
	this->GetWorldCoordImage()->SetDirection(Direction);
	this->GetFlagImage()->SetDirection(Direction);
}


//----------------------------------------------------------------------------
template<class TRealType, unsigned int NDimension>
void
RImage<TRealType, NDimension>
::CopyInformation(const DataObject *data)
{
	// Call the superclass' method first
	Superclass::CopyInformation(data);

	// Return if we have an invalid data object
	if ( !data )
		return;

	// The range image to graft
	ConstPointer Image = NULL;

	// Check if we have a vaild data object
	try
	{
		Image = dynamic_cast<const Self*>(data);
	}
	catch( ... )
	{
		itkExceptionMacro(<<"Could not graft unknown type: exception occured!");
	}
	if ( !Image )
	{
		itkExceptionMacro(<<"Could not graft unknown type: could not cast!");
	}

	// Copy Regions, Spacing, Origin and Direction from ITK (or derived) Images
	CopyImageMetaData(Image->GetRangeImage(),this->GetRangeImage());
	CopyImageMetaData(Image->GetFlagImage(),this->GetFlagImage());
	CopyImageMetaData(Image->GetWorldCoordImage(),this->GetWorldCoordImage());

	// Update the superclass (ONLY for the RImage WRAPPER!!!)
	Superclass::SetLargestPossibleRegion(Image->GetLargestPossibleRegion());
	//this->SetLargestPossibleRegion(Image->GetLargestPossibleRegion());

	// Copy the camera parameters
	for ( unsigned int i = 0; i < CameraParameters::NumCameraParameters; i++ )
		m_CameraParameters[i] = Image->GetCameraParameters()[i];

	// Copy the time stamp
	m_TimeStamp = Image->GetTimeStamp();

	// Copy the payload hash
	m_PayloadHash = Image->GetPayloadHash();
}


//----------------------------------------------------------------------------
template<class TRealType, unsigned int NDimension>
void
RImage<TRealType, NDimension>
::Graft(const DataObject *data)
{
	// Call the superclass' method first
	Superclass::Graft(data);
	
	// The range image to graft
	ConstPointer Source = NULL;

	// Check if we have a vaild data object
	try
	{
		Source = dynamic_cast<const Self*>(data);
	}
	catch( ... )
	{
		itkExceptionMacro(<<"Could not graft unknown type");
	}
	if ( !Source )
	{
		itkExceptionMacro(<<"Could not cast unknown type");
	}

	// Copy the meta-information and remaining regions
	this->CopyInformation(Source);
	this->SetBufferedRegion(Source->GetBufferedRegion());
	this->SetRequestedRegion(Source->GetRequestedRegion());

	// First, check if this image stores more payloads than the input. This is a case that we can't handle...
	/*if ( m_PayloadContainers.size() > Source->m_PayloadContainers.size() )
	{	
		std::cout << "Invalid payload containers detected!" << std::endl;
		std::cout << "SourcePayloads:" << std::endl;
		for ( unsigned int i = 0; i < Source->m_PayloadContainers.size(); i++ )
			std::cout << "	" << Source->m_PayloadContainers[i]->GetIdentifier() << std::endl;
		std::cout << "This payloads:" << std::endl;
		for ( unsigned int i = 0; i < m_PayloadContainers.size(); i++ )
			std::cout << "	" << m_PayloadContainers[i]->GetIdentifier() << std::endl;
		itkExceptionMacro(<<"Cannot graft an RImage that stores less payload containers: " << Source->m_PayloadContainers.size() << " vs. " << m_PayloadContainers.size());
	}*/

	// Second, check if the input image stores more payloads. If so, clone these containers and append them
	if ( Source->m_PayloadContainers.size() > m_PayloadContainers.size() )
	{
		for ( unsigned int i = m_PayloadContainers.size(); i < Source->m_PayloadContainers.size(); i++ )
		{
			GenericPayloadContainerPointer tmp = dynamic_cast<GenericPayloadContainer*>((itk::LightObject*)Source->m_PayloadContainers[i]->CreateAnother());
			tmp->SetIdentifier(Source->m_PayloadContainers[i]->GetIdentifier());
			this->AppendPayloadContainer(tmp);
		}
	}

	// Graft all payload containers
	for ( unsigned int i = 0; i < Source->m_PayloadContainers.size(); i++ )
	{
		m_PayloadContainers[i]->Graft(Source->m_PayloadContainers[i]);
	}

#if 0
	// Graft the internal images as well
	this->GetRangeImage()->Graft(Image->GetRangeImage());
	this->GetWorldCoordImage()->Graft(Image->GetWorldCoordImage());
	this->GetFlagImage()->Graft(Image->GetFlagImage());
#endif
}


//----------------------------------------------------------------------------
template<class TRealType, unsigned int NDimension>
void
RImage<TRealType, NDimension>
::DeepCopy(const DataObject *data)
{
	// The range image to copy
	ConstPointer Source = NULL;

	// Check if we have a vaild data object
	try
	{
		Source = dynamic_cast<const Self*>(data);
	}
	catch( ... )
	{
		itkExceptionMacro(<<"Could not graft unknown type");
	}
	if ( !Source )
	{
		itkExceptionMacro(<<"Could not cast unknown type");
	}

	// Copy the meta-information and remaining regions
	this->CopyInformation(Source);
	this->SetBufferedRegion(Source->GetBufferedRegion());
	this->SetRequestedRegion(Source->GetRequestedRegion());

	// Allocate all subimages. Note that this should not allocate any memory if previous call to allocate used the same regions!
	this->Allocate();

	// First, check if this image stores more payloads than the input. This is a case that we can't handle...
	/*if ( m_PayloadContainers.size() > Source->m_PayloadContainers.size() )
		itkExceptionMacro(<<"Cannot graft an RImage that stores less payload containers: " << Source->m_PayloadContainers.size() << " vs. " << m_PayloadContainers.size());*/

	// Second, check if the input image stores more payloads. If so, clone these containers and append them
	if ( Source->m_PayloadContainers.size() > m_PayloadContainers.size() )
	{
		for ( unsigned int i = m_PayloadContainers.size(); i < Source->m_PayloadContainers.size(); i++ )
		{
			GenericPayloadContainerPointer tmp = dynamic_cast<GenericPayloadContainer*>((itk::LightObject*)Source->m_PayloadContainers[i]->CreateAnother());
			tmp->SetIdentifier(Source->m_PayloadContainers[i]->GetIdentifier());
			this->AppendPayloadContainer(tmp);
		}
	}

	// Deep copy all payload containers
	for ( unsigned int i = 0; i < Source->m_PayloadContainers.size(); i++ )
		m_PayloadContainers[i]->DeepCopy(Source->m_PayloadContainers[i]);

#if 0
	// Range image
	GIIC_IMAGE_DEEPCOPY(RangeImageType, Image->GetRangeImage(), this->GetRangeImage());
	
	// Flag image
	GIIC_IMAGE_DEEPCOPY(FlagImageType, Image->GetFlagImage(), this->GetFlagImage());

	// World coord image
	GIIC_IMAGE_DEEPCOPY(WorldCoordImageType, Image->GetWorldCoordImage(), this->GetWorldCoordImage());
#endif
}


//----------------------------------------------------------------------------
template<class TRealType, unsigned int NDimension>
void
RImage<TRealType, NDimension>
::DisconnectPipeline()
{
	// Disconnect the superclass
	Superclass::DisconnectPipeline();

	// Disconnect the payload
	if ( this->GetRangeImage() )
		this->GetRangeImage()->DisconnectPipeline();
	if ( this->GetWorldCoordImage() )
		this->GetWorldCoordImage()->DisconnectPipeline();
	if ( this->GetFlagImage() )
		this->GetFlagImage()->DisconnectPipeline();
}


//----------------------------------------------------------------------------
template<class TRealType, unsigned int NDimension>
void
RImage<TRealType, NDimension>
::SynchronizeGenericImportImageContainers()
{
	// For conveniences
	typedef unsigned long ElementIdentifier;

	// Range data
	typedef GenericImportImageContainer<ElementIdentifier, RangeType> RangeContainerType;
	typename RangeContainerType::Pointer RangeContainer = dynamic_cast<RangeContainerType*>(this->GetRangeImage()->GetPixelContainer());
	if ( RangeContainer )
	{
		//std::cout << "	sync range" << std::endl;
		RangeContainer->Synchronize();
	}

	// World coord data
	typedef GenericImportImageContainer<ElementIdentifier, WorldCoordType> WorldCoordContainerType;
	typename WorldCoordContainerType::Pointer WorldCoordContainer = dynamic_cast<WorldCoordContainerType*>(this->GetWorldCoordImage()->GetPixelContainer());
	if ( WorldCoordContainer )
	{
		//std::cout << "	sync world coords" << std::endl;
		WorldCoordContainer->Synchronize();
	}

	// Flag data
	typedef GenericImportImageContainer<ElementIdentifier, FlagType> FlagContainerType;
	typename FlagContainerType::Pointer FlagContainer = dynamic_cast<FlagContainerType*>(this->GetFlagImage()->GetPixelContainer());
	if ( FlagContainer )
	{
		//std::cout << "	sync flags" << std::endl;
		FlagContainer->Synchronize();
	}
}


//----------------------------------------------------------------------------
template<class TRealType, unsigned int NDimension>
void
RImage<TRealType, NDimension>
::SetCameraParameters(CameraParameters CameraParameters)
{
	m_CameraParameters = CameraParameters;
}


//----------------------------------------------------------------------------
template<class TRealType, unsigned int NDimension>
CameraParameters&
RImage<TRealType, NDimension>
::GetCameraParameters()
{
	return m_CameraParameters;
}


//----------------------------------------------------------------------------
template<class TRealType, unsigned int NDimension>
const CameraParameters&
RImage<TRealType, NDimension>
::GetCameraParameters() const
{
	return (const CameraParameters&)m_CameraParameters;
}


//----------------------------------------------------------------------------
template<class TRealType, unsigned int NDimension>
void
RImage<TRealType, NDimension>
::Finish()
{
	ComputeRangeToWorldCoords();	
}


//----------------------------------------------------------------------------
template<class TRealType, unsigned int NDimension>
void
RImage<TRealType, NDimension>
::ComputeRangeToWorldCoords()
{
	// Perform transformation
	m_R2WCFilter->SetCameraParameters(m_CameraParameters);
	m_R2WCFilter->SetUseUndistortion(m_UseDistortion);
	m_R2WCFilter->SetInput(this->GetRangeImage());
	m_R2WCFilter->SetFlagImageInput(this->GetFlagImage());
	m_R2WCFilter->GetOutput()->SetRequestedRegion(this->GetRequestedRegion());
	m_R2WCFilter->Update();

	// Set the image and update MTimes
	this->SetWorldCoordImage(m_R2WCFilter->GetOutput());	
}


//----------------------------------------------------------------------------
template<class TRealType, unsigned int NDimension>
void
RImage<TRealType, NDimension>
::ComputeWorldCoordsToRange()
{
	itkExceptionMacro(<<"Transforming from world coordinates to range data is not supported atm!");
}


//----------------------------------------------------------------------------
template<class TRealType, unsigned int NDimension>
typename RImage<TRealType, NDimension>::RangeImagePointer
RImage<TRealType, NDimension>
::GetRangeImage()
{
	return (RangeImagePointer)static_cast<RangeImageType*>(this->GetPayloadContainer(m_RangeDataPayloadIdx)->GetPayload());
}


//----------------------------------------------------------------------------
template<class TRealType, unsigned int NDimension>
typename RImage<TRealType, NDimension>::RangeImageConstPointer
RImage<TRealType, NDimension>
::GetRangeImage() const
{
	return (RangeImageConstPointer)static_cast<const RangeImageType*>(this->GetPayloadContainer(m_RangeDataPayloadIdx)->GetPayload());
}


//----------------------------------------------------------------------------
template<class TRealType, unsigned int NDimension>
typename RImage<TRealType, NDimension>::WorldCoordImagePointer
RImage<TRealType, NDimension>
::GetWorldCoordImage()
{
	return (WorldCoordImagePointer)static_cast<WorldCoordImageType*>(this->GetPayloadContainer(m_WorldCoordDataPayloadIdx)->GetPayload());
}


//----------------------------------------------------------------------------
template<class TRealType, unsigned int NDimension>
typename RImage<TRealType, NDimension>::WorldCoordImageConstPointer
RImage<TRealType, NDimension>
::GetWorldCoordImage() const
{
	return (WorldCoordImageConstPointer)static_cast<const WorldCoordImageType*>(this->GetPayloadContainer(m_WorldCoordDataPayloadIdx)->GetPayload());
}


//----------------------------------------------------------------------------
template<class TRealType, unsigned int NDimension>
typename RImage<TRealType, NDimension>::FlagImagePointer
RImage<TRealType, NDimension>
::GetFlagImage()
{
	return (FlagImagePointer)static_cast<FlagImageType*>(this->GetPayloadContainer(m_FlagDataPayloadIdx)->GetPayload());
}


//----------------------------------------------------------------------------
template<class TRealType, unsigned int NDimension>
typename RImage<TRealType, NDimension>::FlagImageConstPointer
RImage<TRealType, NDimension>
::GetFlagImage() const
{
	return (FlagImageConstPointer)static_cast<const FlagImageType*>(this->GetPayloadContainer(m_FlagDataPayloadIdx)->GetPayload());
}


//----------------------------------------------------------------------------
template<class TRealType, unsigned int NDimension>
void
RImage<TRealType, NDimension>
::SetRangeImage(RangeImagePointer RI)
{
	// Sanity check
	if ( this->GetRequestedRegion() != RI->GetRequestedRegion() )
		itkExceptionMacro(<<"Invalid regions detected:" << this->GetRequestedRegion() << " vs. " << RI->GetRequestedRegion());

	this->GetPayloadContainer(m_RangeDataPayloadIdx)->SetPayload(RI);
	this->Modified();
}


//----------------------------------------------------------------------------
template<class TRealType, unsigned int NDimension>
void
RImage<TRealType, NDimension>
::SetWorldCoordImage(WorldCoordImagePointer WI)
{
	// Sanity check
	if ( this->GetRequestedRegion() != WI->GetRequestedRegion() )
		itkExceptionMacro(<<"Invalid regions detected: " << this->GetRequestedRegion() << " vs. " << WI->GetRequestedRegion());

	this->GetPayloadContainer(m_WorldCoordDataPayloadIdx)->SetPayload(WI);
	this->Modified();
}


//----------------------------------------------------------------------------
template<class TRealType, unsigned int NDimension>
void
RImage<TRealType, NDimension>
::SetFlagImage(FlagImagePointer FI)
{
	// Sanity check
	if ( this->GetRequestedRegion() != FI->GetRequestedRegion() )
		itkExceptionMacro(<<"Invalid regions detected!");

	this->GetPayloadContainer(m_FlagDataPayloadIdx)->SetPayload(FI);
	this->Modified();
}


//----------------------------------------------------------------------------
template<class TRealType, unsigned int NDimension>
void
RImage<TRealType, NDimension>
::SetTimeStamp(TimeStampType TimeStamp)
{
	m_TimeStamp = TimeStamp;
}


//----------------------------------------------------------------------------
template<class TRealType, unsigned int NDimension>
const typename RImage<TRealType, NDimension>::TimeStampType&
RImage<TRealType, NDimension>
::GetTimeStamp() const
{
	return m_TimeStamp;
}


//----------------------------------------------------------------------------
template<class TRealType, unsigned int NDimension>
void
RImage<TRealType, NDimension>
::PrintSelf(std::ostream& os, itk::Indent indent) const
{
	Superclass::PrintSelf(os,indent);
	os << indent << "RImage" << std::endl;
	os << indent << indent << "Payload containers" << std::endl;
	for ( unsigned int i = 0; i < m_PayloadContainers.size(); i++ )
		os << indent << indent << indent << "Payload #" << i << ": " << m_PayloadContainers[i]->GetIdentifier() << std::endl;
}


} // end namespace ritk
