/********************************************************************/
/* Copyright (c) 2017 System fugen G.K. and Yuzi Mizuno          */
/* All rights reserved.                                             */
/********************************************************************/
#ifndef _MGSBRepTP_HH_
#define _MGSBRepTP_HH_

#include <assert.h>
#include <memory>
#include "mg/LBRep.h"

// MGSBRepTP.h
//

class MGSurface;
class MGLBRep;
class MGOfstream;
class MGIfstream;
/** @file */
/** @addtogroup GEORelated
 *  @{
 */

///Defines Tangent Plane Line B-Representation Class.

///Tangent plane is a line b-representation of (unit)normal vector of
///tangent plane along surface perimeter.
class MG_DLL_DECLR MGSBRepTP{

public:

///String stream Function.
MG_DLL_DECLR friend std::ostream& operator<< (std::ostream&, const MGSBRepTP& );

//////////// Constructor ////////////

///Default Constructor, will be set as no TPs' are specified.
MGSBRepTP();

///Copy Constructor.
MGSBRepTP(const MGSBRepTP&);

///Compute TP of four boundaries of a Surface B-Rep.
MGSBRepTP(const MGSurface& srf);
	  
//////////// Destructor ////////////

~MGSBRepTP();

//////////// Operator overload. ////////////

///Assignment.
MGSBRepTP& operator=(const MGSBRepTP&);

//////////// Member Function ////////////

/// Compute the maximum (absolute) cos value of between vector deris[i](t) 
/// and vector this->TP(i)(t) for i=0,1,2,3, where t is a common
/// parameter of the data point obtained from deris[i]'s knot vector.
///Function's return value is the max out of cosmax[.].
double get_perimeters_max_cos(
	const MGPvector<MGLBRep>& deris,     ///< the size must be 4.
	double taumax[4], ///< parameter on which the maximum value attains will be stored.
	double cosmax[4]  ///< the maximum value will be stored.
)const;

/// Compute the maximum (absolute) sin value of between vector srf.normal(uv(t))
/// and vector this->TP(i)(t) for i=0,1,2,3, where perim[i] is 
/// the same as srf.perimeter_curve(i), and t is a common parameter
/// of deris[i] and TP(i).
///Function's return value is the max out of sinmax[.].
double get_perimeters_max_sin(
	const MGSurface& srf,    ///< surface which must corresponds to this object.
	double         taumax[4],///< parameters on which the maximum value attains will be stored.
	double         sinmax[4],///< the maximum value will be stored.
	bool*          eval=0	///<indicates perimeters to evalate if eval!=null,
			///<When eval[i] is true, perimeter i is evaluated for 0<=i<=3.
)const;

///Compute maximun abs(cons(theta)), where theta=angle of TP(i) and  corresponding 
///edge_crvl[i]'s start and end points' tangent vector.
double max_cos(
	const MGCurve*	perimeter[4]///<��E����X�g(vmin,umax,vmax,umin���,����0,1,2,3���)
)const;

///Compute maximun abs(cons(theta)), where theta=angle of TP(i) and  corresponding 
///edge_crvl[i]'s start and end points' tangent vector.
double max_cos(
	const MGPvector<MGLBRep>& perimeters///<��E����X�g(vmin,umax,vmax,umin���,����0,1,2,3���)
)const;

///Return if i-th perimeter's TP specified(true) or not.
///i=0, 2 are v=min and max u-parameter line.
///i=1, 3 are u=max and min v-parameter line.
bool specified(int i) const{assert(i<4); return m_TP[i]!=0;};

///Set i-th perimeter's TP as a null, as an unspecified one.
void set_TP_null(int i);

///Set i-th perimeter's TP(copy version).
void set_TP(int i, const MGLBRep& tp);

///Set i-th perimeter's TP(unique_ptr version).
void set_TP(int i, std::unique_ptr<MGLBRep>& tp);

///Return i-th perimeter's TP.
const MGLBRep& TP(int i) const{assert(i<4);return *(m_TP[i]);}
MGLBRep& TP(int i) {assert(i<4);return *(m_TP[i]);}

MGLBRep** TP(){return m_TP;};

private:
//////////// Member Data ////////////
	MGLBRep* m_TP[4];	///<Tangent Plane will be stored.
				///<Tangent plane m_TP[i] is a line b-representation of
				///<(unit)normal vector along the i-th perimeter.
				///<Parameter range of the TP is the same as u or v parameter
				///<range of the corresponding surface representation.
	///< m_TP[0]: v=min boundary line, m_TP[1]: u=max boundary line
	///< m_TP[2]: v=max boundary line, m_TP[3]: u=min boundary line

};

///Construct a tangent plane LBRep of a curve wcrv. wcrv is a world coordinate
///curve that lies on a surface srf.
///TP_from_world_curve is for the users who do not know the parameter
///representation of wcrv of the surface srf. If you know the parameter
///representation of wcrv, you should use TP_from_parameter_curve.
///TP_from_parameter_curve's computation time is much smaller
///than TP_from_world_curve's.
///Let f(t) be wcrv whose parameter is t. Then the parameter of this function's
///output is the same as t. Let g(t) be the output, then g(t)=normal at srf(u,v).
///where srf(u,v)=f(t).
MG_DLL_DECLR MGLBRep TP_from_world_curve(
	const MGSurface& srf,///<����
	const MGCurve& wcrv,///<�����
	int order,	///<�����J�[�u��I�[�_
	int& error	///<�G���[�R�[�h  0:OK, !=0 error code when constructing LBRep.
);

///Construct a tangent plane LBRep of a curve pcrv. pcrv is a parameter coordinate
///curve of a surface srf. wcrv is a target curve that lies on the surface srf, is
///world coordinate representation of pcrv. Output MGLBRep's parameter is 
///Let f(t) be wcrv whose parameter is t. Then the parameter of this function's
///output is the same as t. Let g(t) be the output, then g(t)=normal at srf(u,v).
///where srf(u,v)=f(t).
///pcrv���������������(u,v)�\�����Q�������A
///����Q����������������A�������������A
///���wcrv��������\����������������B
///wcrv��S����P��������(x,y,z)���E��W�\����B
MG_DLL_DECLR MGLBRep TP_from_parameter_curve(
	const MGSurface& srf,	///<����
	const MGCurve& pcrv,	///<�����(������p�����[�^�J�[�u)
	const MGCurve& wcrv,	///<�����(��E��W��J�[�u)
	int order,			///<�����J�[�u��I�[�_
	int& error	///<�G���[�R�[�h  0:OK, !=0 error code when constructing LBRep.
);

/** @} */ // end of GEORelated group

#endif