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

	Program:		Range Imaging Toolkit (RITK)
	Module:			ritkRImageActorPipeline.h
	Version:		$Revision: 1821 $
	Date:			$Date: 2011-10-02 15:41:17 +0200 (So, 02 Okt 2011) $

	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 RIMAGEACTORPIPELINE_H__
#define RIMAGEACTORPIPELINE_H__

#include "ritkVTK.h"

#include "ritkRImage.h"
#include "ritkRImageVTKData.h"
#include "ritkActorPipeline.h"
#include "ritkLUTData.h"

#include <vtkScalarBarActor.h>
#include <vtkLookupTable.h>


namespace ritk
{

/**	@ingroup	ritkVTK
 *	@class		RImageActorPipeline
 *	@author		Jakob Wasza
 *	@brief		Actor pipeline for range image data
 *
 *	@details
 *	This class provides an actor pipeline for range image data. The actor's associated
 *	VTK poly data is thereby created from a RImage object or taken from a VTK poly data
 *	object. The former is a very simple and easy to use method that generates the actor's
 *	poly data automatically (using a user defined mesh structure and color mode),
 *	whereas the latter implies that the RImage object is already "converted" to a poly data
 *	by the user and just needs to be visualized. A exemplary scenario for the latter would be 
 *	if a VTK poly data is already created from the range image for the purpose of surface feature 
 *	computation and the scalars for the poly data's points are set in accordance to the feature values.
 *	For convenience, the second method for setting the data may also take an additionally RImage object
 *	that, coupled with the color mode, eventually defines the scalars.\n
 *	As the creation of a VTK poly data out of a RImage object is a rather expensive operation from a 
 *	computational point of view you should use the second method if you already have created a valid 
 *	VTK poly data. \n
 *	Note: We assume that the ordering of poly data elements and range data elements is identic.
 **/
class RITKVTK_EXPORT RImageActorPipeline : public ActorPipeline
{
public:
	/// Casting
	vtkTypeMacro(RImageActorPipeline,ActorPipeline);

	/// Object creation
	static RImageActorPipeline *New();

	/**	@name The input types */
	//@{
	typedef ActorPipeline::PolyDataPointer	PolyDataPointer;
	typedef const PolyDataPointer			PolyDataConstPointer;
	typedef RImageF2						RImageType;
	typedef RImageType::Pointer				RImagePointer;
	typedef RImageType::ConstPointer		RImageConstPointer;
	//@}

	/**	@name Visualization modes */
	//@{
	/// The available types
	typedef enum VisualizationMode
	{
		MONOCHROME,
		ZBUFFER,
		RGB,
		FLAGS
	} VisualizationMode;

	/**	@brief	Set the visualization mode
	 *	@param	Mode	The mode to be used
	 *
	 *	@brief
	 *	This method will set the visualization mode for the range image actor.
	 *	The default visualization mode is monochrome. \n
	 *	This method is in compliance with the thread safety concept of the actor pipeline.
	 *	@sa VisualizationMode
	 */
	void SetVisualizationMode(VisualizationMode Mode);

	/**	@brief	Use the built in lookup table
	 *	@param	UseLUT	Enable or disable
	 *
	 *	@details
	 *	Enable or disable LUT visualization. The built in LUT maps the 
	 *	raw intensity values to a color jet. By default, the LUT is disabled. \n
	 *	This method is in compliance with the thread safety concept of the actor pipeline.
	 */
	void UseLUT(bool UseLUT);
	//@}

	
	/** @name The poly data type */
	//@{
	/// Poly data type
	typedef enum RImageVTKData::PolyDataType PolyDataType;

	/**	@brief	Set the poly data type 
	 *	@param	Type	The type
	 *
	 *	@brief
	 *	Set the poly data type for creating the data. Note that this value has only an 
	 *	effect if you set the data through the SetData(RImageConstPointer) method. 
	 *	The default is the point cloud. \n
	 *	This method is in compliance with the thread safety concept of the actor pipeline.
	 */
	void SetPolyDataType(PolyDataType Type);
	//@}

	/// From ActorPipeline
	void SetData(PolyDataPointer Data, bool DeepCopy=true);

	/**	@brief	Set the data using a VTK poly data
	 *	@param	PolyData	VTK poly data that holds the range data
	 *	@param	Image		Optional RImage that holds the range data
	 *
	 *	@details
	 *	This method will set the actual actor data. If no valid RImage pointer
	 *	is passed to this method, the poly data argument will be passed to the 
	 *	superclass' SetData() method directly where a deep copy is performed. 
	 *	If a range image is available, a deep copy of the original poly data is 
	 *	performed, the copy's colors modified in accordance to the provided range
	 *	image, and the copy passed to the superclass' SetData() method where no 
	 *	deep copy is performed. The intensities (pixel/vertex colors) are computed as 
	 *	specified by the SetVisualizationMode() method. \n
	 *	This method is in compliance with the thread safety concept of the actor pipeline.
	 */
	void SetData(PolyDataConstPointer PolyData, const RImageType *Image=NULL);

	/**	@brief	Set the data using a range image only
	 *	@param	Image	The RImage that holds the data
	 *
	 *	@details
	 *	This method will set the actual actor data. The VTK poly data is thereby 
	 *	created from a RImage using the RImageVTK class. The poly data is created
	 *	in occordance to the specified mesh type set by SetPolyDataType().
	 *	The intensities (pixel/vertex colors) are computed as specified by the 
	 *	SetVisualizationMode() method. The poly data type used can be set with 
	 *	the SetPolyDataType() method. \n
	 *	This method is in compliance with the thread safety concept of the actor pipeline.
	 */
	void SetData(const RImageType *Image);

	/**	@brief	Set the interval (min/max) for the range LUT
	 *	@param	min		the lower interval bound
	 *	@param	max		the upper intereval bound
	 *
	 *	@details
	 *	This method will set the interval for the range LUT. If the LUT mode is NOT requested
	 *	this method has no effect and the range values will be mapped to [0:255] and visualized
	 *	as greyscales.
	 */
	void SetRangeInterval(float min, float max);


	/**	@brief	Set the interval (min/max) for the grayscale LUT
	 *	@param	min		the lower interval bound
	 *	@param	max		the upper intereval bound
	 *
	 *	@details
	 *	This method will set the interval for the grayscale LUT. If the LUT mode is NOT requested
	 *	this method has no effect and the range values will be mapped to [0:255] and visualized
	 *	as greyscales.
	 */
	void SetRGBInterval(float min, float max);

	/// Set the visibility of the scalarbar associated to this actor pipeline
	void SetScalarBarVisibility(bool b);


public:
	/// The scalar bar actor that is associated to this actor. Public visibility allows adding the actor to a renderer
	vtkSmartPointer<vtkScalarBarActor> m_ScalarBarActor;


protected:
	/// Constructor
	RImageActorPipeline();
	/// Destructor
	~RImageActorPipeline();

	/// Compute a colored poly data as specified by the visualization mode
	PolyDataPointer ComputeColoredPolyData(PolyDataConstPointer Data, const RImageType *Image, VisualizationMode Mode, bool UseLUT);

	/// Compute a colored poly data form the poly data scalars
	PolyDataPointer ComputeColoredPolyData(PolyDataConstPointer Data);

	/// Update the superclass' mapper based on whether to use a LUT
	void UpdateMapper(VisualizationMode Mode, bool UseLUT);

protected:
	/// The visualization mode
	VisualizationMode m_VisualizationMode;
	/// LUT usage
	bool m_UseLUT;
	/// The LUT that is used
	vtkSmartPointer<vtkLookupTable> m_LUT;
	/// Interval for the range LUT
	float m_RangeInterval[2];
	/// Interval for the RGB LUT
	float m_RGBInterval[2];

	/// Visibility of the scalar bar
	bool m_ScalarBarVisibility;

	/// The poly data type
	PolyDataType m_PolyDataType;
	/// The RImageVTKData object
	vtkSmartPointer<RImageVTKData> m_RImageVTKData;
};


} // end namespace ritk


#endif // RIMAGEACTORPIPELINE_H__