//*****************************************************************************************
// Truevision - a 3d modeler for gnome and povray
//
// spline2d.h
//
// Vincent LE PRINCE <vincentleprince@users.sourceforge.net>
// Copyright (C) 2000-2005 Vincent LE PRINCE
// This file is part of the TRUEVISION Package

//   This program 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 2 of the License, or
//   (at your option) any later version.
//
//   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 the
//   GNU General Public License for more details.
//
//   You should have received a copy of the GNU General Public License
//   along with this program; if not, write to the Free Software
//   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */ 
//*******************************************************************************************
#ifndef TV_SPLINE_H
#define TV_SPLINE_H
using namespace std;
#include "object3d.h"
#include <vector>

enum stype {
	TV_SPLINE2D_LINEAR = 0,
	TV_SPLINE2D_QUADRATIC,
	TV_SPLINE2D_CUBIC,
	TV_SPLINE2D_BEZIER,	
};
typedef stype SplineType;



class Spline2DPoint {
	private:
		float x, y;
		float control1[2], control2[2];
	
	public:
		Spline2DPoint() { x=0; y=0; }
		Spline2DPoint( float a, float b );
		Spline2DPoint( float a, float b, float c1x, float c1y, float c2x, float c2y );
		Spline2DPoint * auto_copy() { return new Spline2DPoint( x, y, control1[0], control1[1], control2[0], control2[1]); }
		
		void display( bool for_lathe ) { if ( for_lathe ) glVertex3f( x, y, 0.0 ); else glVertex3f( x, 0.0, y ); }
		void display_ctrl1( bool for_lathe ) {  if ( for_lathe ) glVertex3f( x+control1[0], y+control1[1], 0 ); else  glVertex3f( x+control1[0], 0, y+control1[1] ); }
		void display_ctrl2( bool for_lathe ) {  if ( for_lathe ) glVertex3f( x+control2[0], y+control2[1], 0 ); else  glVertex3f( x+control2[0], 0, y+control2[1] );}
		void display_rotated( float angle, bool invert_normal  );
		void save( ofstream & file );
		void load(  ifstream & file, char *tag );
		void output_to_povray( ofstream & file, int spline_type, bool first, bool for_lathe );
		float getx() { return x; }
		float gety() { return y; }
		void get( float * target ) { target[0] = x; target[1] = y; }
		void get_control1( float *target ) { target[0] = control1[0]; target[1] = control1[1]; }
		void get_control2( float *target ) { target[0] = control2[0]; target[1] = control2[1]; }
		void set( float a, float b ) { x = a; y = b; }
		void set( float a, float b, float c1x, float c1y, float c2x, float c2y ) { x = a; y = b; control1[0]=c1x; control1[1]=c1y; control2[0]=c2x; control2[1]=c2y; }
};

 class Spline2D {
	 private:
		vector<Spline2DPoint*> Points;
	 	SplineType type;
	 	int subdivisions;
		bool closed;
	 	bool for_lathe;
		
	public:
		Spline2D( SplineType type, int subdivisions );
		~Spline2D();
		Spline2D * auto_copy();
	
		void set_type( SplineType atype ) { type = atype; }
		void set_subdivisions( int sub ) { subdivisions = sub; }
	
		void add_point( Spline2DPoint *pt ) { Points.push_back( pt ); }
		void add_point( float x, float y );
		void add_point( float x, float y, float c1x, float c1y, float c2x, float c2y );
		void set_point( int i, float x, float y ) { if ( for_lathe && x < 0 ) x = 0; Points[i]->set( x, y ); }
		void set_point( int i, float x, float y, float c1x, float c1y, float c2x, float c2y );
		void set_for_lathe( bool val = true  ) { for_lathe = val; }
		float getx( int pt ) { return Points[pt]->getx(); }
		float gety( int pt ) { return Points[pt]->gety(); }
		void get_point_ctrl1( int pt, float *target ) { Points[pt]->get_control1( target ); }
		void get_point_ctrl2( int pt, float *target ) { Points[pt]->get_control2( target ); }
		void append();
		void prepend();
		void insert( int i );
		void delete_point( int selected );
		
		void display_point( int i ) { Points[i]->display( for_lathe ); }
		void display_point_ctrl1( int i ) { Points[i]->display_ctrl1( for_lathe ); }
		void display_point_ctrl2( int i ) { Points[i]->display_ctrl2( for_lathe ); }
		void display_point_rotated( int i, float teta, bool norm ) { Points[i]->display_rotated( teta, norm ); }	
		void save( ofstream & file );
		bool load( ifstream & file, char *tag );
		void output_to_povray( ofstream & file );
		
		void get_segments( int & pt_num, float  * & xcoords, float * & ycoords );
		void gl_display_segments();
		int size() { return Points.size(); }
 };

#endif
