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

	Program:		Range Imaging Toolkit (RITK)
	Module:			ritkRayCasterBase.h
	Version:		$Revision: 2908 $
	Date:			$Date: 2012-04-03 22:28:42 +0200 (Di, 03 Apr 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

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


#ifndef RITKRAYCASTERBASE_H__
#define RITKRAYCASTERBASE_H__

#include <itkImageToImageFilter.h>
#include <itkSimpleDataObjectDecorator.h>

#include <vnl/vnl_double_3x4.h>
#include <vnl/vnl_double_3x3.h>

using namespace itk;

namespace ritk
{

/**	@ingroup	Visualization
 *	@class		RayCasterBase
 *	@author		Jakob Wasza
 *	@brief		Basic interface for volume ray casting
 *
 *	@details
 *	This class provides the very basic interface for volume ray casting in RITK. In particular, this includes the definition
 *	of a ray caster as a subclass of itk::ImageToImageFilter and the interface for setting the projection matrix and the projection image size.
 *	Furthermore, this base class handles correct output information creation and generation of the input region that is by default not supported
 *	in itk::ImageToImage filters for different dimensionality in the input and output. \n
 *	Note that this base class does not provide an implementation of (Threaded)GenerateData. This is the task of subclasses where the actual
 *	ray casting has to be done. \n
 *	Within this base class, we by default assume that a given projection matrix incorporates \n
 *		-	the pure projection model (orthographic/perspective) P \n
 *		-	the camera intrinsics K \n
 *		-	the extrinsic linear transformation T \n
 *	as K*P*T. However, as this base class does not perform any computations, base classes can define another behaviour. \n
 *	Note that though this base class is defined in the ritkVisualization module, usage should not be restricted to visualization purposes.
 */
template<class TInputVolume, class TOutputImage>
class RayCasterBase : public itk::ImageToImageFilter<TInputVolume, TOutputImage>
{
public:
	/** @name Typedefs */
	//@{

	/** @name Standard typedefs */
	//@{
	typedef RayCasterBase											Self;
    typedef itk::ImageToImageFilter<TInputVolume, TOutputImage>		Superclass;
    typedef itk::SmartPointer<Self>									Pointer;
    typedef itk::SmartPointer<const Self>							ConstPointer;
	//@}

	/** @name Input typedefs */
	//@{
	typedef TInputVolume											InputVolumeType;
	typedef typename InputVolumeType::Pointer						InputVolumePointer;
	typedef typename InputVolumeType::ConstPointer					InputVolumeConstPointer;
	typedef typename InputVolumeType::PixelType						InputVolumePixelType;
	typedef typename InputVolumeType::RegionType					InputVolumeRegionType;
	//@}
	
	/** @name Output image typedefs */
	//@{
	typedef TOutputImage											OutputImageType;
	typedef typename OutputImageType::Pointer						OutputImagePointer;
	typedef typename OutputImageType::ConstPointer					OutputImageConstPointer;
	typedef typename OutputImageType::PixelType						OutputImagePixelType;
	typedef typename OutputImageType::RegionType					OutputImageRegionType;
	typedef typename OutputImageType::SpacingType					OutputImageSpacingType;
	typedef typename OutputImageType::PointType						OutputImagePointType;
	//@}


	/** @name Projection matrix typedefs */
	//@{
	typedef vnl_double_3x4											ProjectionMatrixType;
	typedef itk::SimpleDataObjectDecorator<ProjectionMatrixType>	ProjectionMatrixDecoratorType;
	typedef vnl_double_3x3											ProjectionMatrixInverseType;
	//@}

	//@}

	/// Object creation
	itkNewMacro(Self);

	/// RTTI
	itkTypeMacro(RayCasterBase,itk::ImageToImageFilter);

	/** @name Dimensions macros */
	//@{
	itkStaticConstMacro(InputImageDimension,  unsigned int, InputVolumeType::ImageDimension);
	itkStaticConstMacro(OutputImageDimension, unsigned int, OutputImageType::ImageDimension);
	//@}

	/**	@name Set/get the projection matrix.*/
	//@{
	itkSetDecoratedInputMacro(ProjectionMatrix, ProjectionMatrixType, 1);
	//@}

	/**	@name Set/get the size (in pixel) of the output image. Default is 512x512. */
	//@{
	itkSetMacro(OutputSize, typename OutputImageRegionType::SizeType);
	itkGetMacro(OutputSize, typename OutputImageRegionType::SizeType);
	//@}

	/**	@name Overloaded to support 3D-2D projection. Note that future versions might use the CallCopy mechanism instead of GenerateInputRequestedRegion. */
	//{
	virtual void GenerateInputRequestedRegion();
	virtual void GenerateOutputInformation();
	//@}

protected:
	/// Constructor
	RayCasterBase();
	/// Destructor
	virtual ~RayCasterBase();

protected:
	/// The requested size of the output image
	typename OutputImageRegionType::SizeType m_OutputSize;
	
private:
	/// purposely not implemented
	RayCasterBase(Self&);
	/// purposely not implemented
	void operator=(const Self&);
};


} // namespace ritk

#endif // RITKRAYCASTERBASE_H__