/* -*- mia-c++ -*-
 *
 * This file is part of viewitgui - a library and program for the
 * visualization of 3D data sets. 
 *
 * Copyright (c) Leipzig, Madrid 1999-2013 Mirco Hellmann, Gert Wollny
 *
 * viewitgui is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * viewitgui 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 the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with viewitgui; if not, see <http://www.gnu.org/licenses/>.
 */


#ifndef __clip_plane
#define __clip_plane

#include <viewit/slice.hh>

#include <mia.hh>
using namespace mia; 



typedef T4DVector<double> T4DDVector; 

extern const string type_TClipPlane;
#define CLIPPLANE_CLASSNAME "TClipPlane"
#define XYCLIPPLANE_CLASSNAME "TXYClipPlane"
#define XZCLIPPLANE_CLASSNAME "TXZClipPlane"
#define YZCLIPPLANE_CLASSNAME "TYZClipPlane"
#define FREECLIPPLANE_CLASSNAME "TFreeClipPlane"

/// a class to handle OpenGL clip planes
/**
   This class is there to handle clip planes in OpenGL.
   Each object in the scene can enable/disable all available clip planes individually. 
   The clip plane can be moved around, and the side to be clipped can be flipped. 
   
 */


class TClipPlane : public TSlice {
	int enabled;
	int no;
	static unsigned char elements[8];	
protected:	
	C3DFVector  strip[4];
	T4DDVector eqn; 		
	bool flipped;
	virtual void calc_strip()=0;
public:
	TClipPlane(const string& name,int _no);
	TClipPlane(const string& name,const C3DFVector& normal, float dist ,int _no);	
	~TClipPlane();
	
	virtual const string& get_type() const {
		return type_TClipPlane;
	}

	/// flips the side to be clipped
	void flip() {
		eqn *= - 1.0f;
		flipped = !flipped;
	}
	
	/// increments the slice index
	virtual void inc_slice();
	
	/// decrements the slice index
	virtual void dec_slice();
	
	/** sets the slice index
	    \param new_slice the new index
	*/
	virtual void set_slice(float new_slice);
	
	/** get the index of the current slice
	    \returns indexof the current slice
	*/
	virtual float get_slice()const;
	
	/** get the range this slice can be moved
	    \param from first slice index
	    \param to last slice index
	*/
	virtual void get_slice_range(float &from, float &to) const;
	
	virtual const char* get_classname()const;
	virtual void get_classname_list(list<string> *classlist) const;
	
	void enable();
	void disable();
	void use_clip_plane() const;
	int get_no()const {
		return no; 
	}
	
	bool is_enabled()const{
		return enabled > 0; 
	}
	
protected:
	virtual bool do_handle_key_event(int key); 
	virtual bool do_handle_command_event(PEventInfo info);
	virtual void do_gl_draw(const TCamera& c) const;
};

/// an axial clip plane
class TXYClipPlane: public TClipPlane {
protected:
	virtual void calc_strip();
public:
	TXYClipPlane();
};

/// a coronal clip plane
class TXZClipPlane: public TClipPlane {
protected:
	virtual void calc_strip();
public:
	TXZClipPlane();
};

/// a saggital clip plane
class TYZClipPlane: public TClipPlane {
protected:
	virtual void calc_strip();
public:
	TYZClipPlane();
};


/// a free clip plane
class TFreeClipPlane: public TClipPlane {

private:
	C3DFVector	__vc;
	TCamera *	__camera; 
	unsigned short	__points_given;
	C3DFVector	__P1;
	C3DFVector	__P2;
	C3DFVector	__loc3d;
	
public:
	TFreeClipPlane(TCamera *camera);

	/** rotates the clipplane normal 
	    \param rot the rotation around the x,y,z-axis (in that order applied)
	*/
	void rot(const C3DFVector& rot);
	
	/** sets the clipping plane by three points
	    \param p1 first point
	    \param p2 second point
	    \param p3 third point
	*/
	void set_position(const C3DFVector& p1, const C3DFVector& p2, const C3DFVector& p3);
	
	virtual const char* get_classname()const;
	virtual void get_classname_list(list<string> *classlist)const;

protected:
	virtual void calc_strip();
	virtual bool do_handle_command_event(PEventInfo info);
	virtual bool do_handle_mouse_event(int button, int x, int y);
	virtual void do_gl_draw(const TCamera& c) const; 
	virtual void do_unselect();
};

#endif
