/********************************************************************/
/* Copyright (c) 2019 System fugen G.K. and Yuzi Mizuno          */
/* All rights reserved.                                             */
/********************************************************************/

/** @file QSReshape.h
 *  This is an internal header file, included by other QS headers.
 *  You should not attempt to use it directly.
 *
 *  Declaration for class %QSReshape. 
 */
#if !defined( __QSRESHAPE_H__)
#define __QSRESHAPE_H__
#include "mg/SBRepTP.h"

class MGLBRep;
class MGSBRepVecTP;

//! @brief A class which restructure a surface with given image curve.
class QSReshape{
public:
	//--------------------------------------------------
	// 2004 新接続四辺面対応
	//--------------------------------------------------
	//@{
	//! @brief Standard constructor.
	//! @param perims       Perimeter curves.
	//! @param tp           TP object.
	//!
	//! assert(perims[i] != 0) for all i.
	//! and perim[i] must corresponds to tp.TP(i).
	QSReshape(const MGLBRep* perims[4]);
	QSReshape(const MGCurve* perims[4]);
	QSReshape(MGLBRep* perims[4]);
	QSReshape(MGCurve* perims[4]);
	//@}

	/// A constructor.
	QSReshape(
		const MGLBRep* vmin, //!< perimeter[0] of a surface. 
		const MGLBRep* umax, //!< perimeter[1] of a surface. 
		const MGLBRep* vmax, //!< perimeter[2] of a surface. 
		const MGLBRep* umin  //!< perimeter[3] of a surface. 
		);

	/// The destructor.
	~QSReshape();

public:
	//! @brief Main routine.
	//! @param blu     1D blending curve along u-dir.(both ranges of parameter and value are [0, 1])
	//! @param blv     1D blending curve along v-dir.(both ranges of parameter and value are [0, 1])
	//! @param imgcrv  A curve that controls @a srf.
	//! @param srf     Output. Specify an empty (default) object of class %MGSBRep.
	//!
	//! @a imgcrv must satisfy that its each endpoint lies on within MGTolerance::wc_zero()
	//! one of the perimeter curves.
bool reshape(
	const MGSBRepTP& tp,
	const MGCurve&   blu,
	const MGCurve&   blv,
	MGSBRep&         srf,
	const MGCurve*   imgcrv = 0 //!< image curve
);

bool reshape(
	const MGSBRepTP& tp,
	MGSBRep&         srf,
	const MGCurve*   imgcrv = 0
);

	//--------------------------------------------------
	// 2004 新接続四辺面対応
	//--------------------------------------------------
bool reshape(
	MGSBRepVecTP& subtps,  // 部分TP曲線列
	MGSBRep&              srf,
	const MGCurve*        imgcrv = 0
);

private:
	//! @brief Obtains abscissa of data point for the isocurves.
	void abscissa(const MGSBRep& srf, MGKnotVector& t, MGNDDArray& tau) const;

	//! @brief Creates a surface from control points of isocurves.
	MGSBRep create_surface();

	//! @brief An auxiliary function to is_u_iso().
	//! @return A bool indicates whether or not found positions 
	//! on perimeter curves each endpoint of @a imgcrv coincides.
	//!
	//! Note that MGTolerance::wc_zero() is used to regard
	//! the two positions as the same or not.
	bool find_perim_isect(
		const MGCurve& imgcrv, //!< image curve
		MGVector&      dirs,   //!< direction at the point of a perimeter curve
		                       //!< that the start point of imgcrv lies on
		MGVector&      dire,   //!< direction at the point of a perimeter curve
		                       //!< that the end point of imgcrv lies on
		MGVector&      imgs,   //!< direction at the start point of imgcrv
		MGVector&      imge,   //!< direction at the end point of imgcrv
		int&           peris,  //!< index of perimeter the start point of imgcrv lies on
		int&           perie   //!< index of perimeter the end point of imgcrv lies on
		) const;

	//! @brief Returns true if isocurves we want is u curves.
	bool is_u_iso(
		const MGCurve& imgcrv, //!< image curve
		const MGVector& dirs,  //!< direction at the point of a perimeter curve
		                       //!< that the start point of imgcrv lies on
		const MGVector& dire,  //!< direction at the point of a perimeter curve
		                       //!< that the end point of imgcrv lies on
		const MGVector& imgs,  //!< direction at the start point of imgcrv
		const MGVector& imge,  //!< direction at the end point of imgcrv
		int peris,             //!< index of perimeter the start point of imgcrv lies on
		int perie              //!< index of perimeter the end point of imgcrv lies on
		) const;

	/// Transforms isocurves so that they pass through a point on @a imgcrv.
	void move_isocurve(const MGCurve& imgcrv);

	//! @brief Obtains u curves on qsurf and saves them.
	//! @param raw surface.
	void set_isocurve(const MGSBRep& qsurf);

// Data members.
private:
	const MGCurve*        __perimcrv[4]; //!< 0-vmin,1-umax,2-vmax,3-umin.
	MGSBRepTP             __tp;          //!< for work
	std::vector<MGLBRep>  __ucrvs;       //!< u-curves
	MGKnotVector          __knotu;       //!< for work
	MGKnotVector          __knotv;       //!< for work
};

#endif // __QSRESHAPE_H__
