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

#if !defined(__MGCALC_RECT_H__)
#define __MGCALC_RECT_H__

#include <iosfwd>
#include <memory>
#include "mg/LBRep.h"
#include "mg/Plane.h"

class MGCurve;
class MGPlane;
class MGPosition;

namespace mgcalc{	
	/// class MGRect
	///
	/// 矩形カーブ生成クラス
	class MGRect{
	public:
		MGRect();
		MGRect(const MGRect& other);
		MGPosition corner(int i) const;
		void clear(){m_polyline.reset();};

		/**
		 *  @brief  2コーナーを与えて矩形カーブを生成する
		 *  @param  plane  矩形が乗る平面に平行な平面
		 *  @param  corner1  矩形の頂点
		 *  @param  corner2  @a corner1 の対角線上の向かいの頂点のヒント
		 *
		 *  もし @a corner2 が @a corner1 を通り @a plane に平行な平面に
		 *  乗っていない場合、@a corner2 は平行な平面に面直投影され、
		 *  その点が @a corner1 の対角線上の向かいの頂点となる。
		 */
		bool create_from_corner(
			const MGPlane&    plane,
			const MGPosition& corner1,
			const MGPosition& corner2
			);

		/**
		 *  @brief  中心とひとつのコーナーを与えて矩形カーブを生成する
		 *  @param  plane  矩形が乗る平面に平行な平面
		 *  @param  center  矩形の重心
		 *  @param  corner  矩形の始点
		 *
		 *  もし @a corner が @a center を通り @a plane に平行な平面に
		 *  乗っていない場合、@a corner は平行な平面に面直投影され、
		 *  その点が矩形の1頂点となる。
		 */
		bool create_from_center(
			const MGPlane&    plane,
			const MGPosition& center,
			const MGPosition& corner
			);

		/**
		 *  @brief  エッジ一本と対辺にありそうな点を指定して矩形カーブを生成
		 *  @param  es  エッジの始点
		 *  @param  ee  エッジの終点
		 *  @param  p   エッジの対辺にありそうな点
		 */
		bool create_from_edge(
			const MGPosition& es,
			const MGPosition& ee,
			const MGPosition& p
			);
		
		const MGCurve* curve() const;///< Get the pointer to m_polyline.
		void draw(mgSysGL& sgl) const;
		const MGPlane* plane() const;
		MGCurve* release();
		bool valid() const;

		friend std::ostream& operator<<(std::ostream& os, const MGRect& rect);

	private:
		std::unique_ptr<MGLBRep>  m_polyline;
		MGPlane m_plane;
	};

	// class MGRoundRect
	//
	// 角の丸まった矩形カーブ生成クラス
	class MGRoundRect{
	public:
		MGRoundRect();
		MGRoundRect(const MGRoundRect& other);
		const MGCurve* curve() const;///< Get the pointer to m_roundRect.
		void clear(){m_roundRect.reset();};

		/**
		 *  @brief  2コーナーを与えて角の丸い矩形カーブを生成する
		 *  @param  rect     矩形曲線
		 *  @param  through  角の円弧上の点
		 *
		 *  もし @a corner2 が @a corner1 を通り @a plane に平行な平面に
		 *  乗っていない場合、@a corner2 は平行な平面に面直投影され、
		 *  その点が @a corner1 の対角線上の向かいの頂点となる。
		 *
		 *  もし @a through が角の丸みを指定できない場合、この関数は
		 *  丸みの半径を min(矩形の辺の長さ) * 0.5 として計算する。
		 */
		bool create(
			const MGRect*     rect,
			const MGPosition& through
			);

		/**
		 *  @brief  2コーナーを与えて角の丸い矩形カーブを生成する
		 *  @param  rect     矩形曲線
		 *  @param  radius   円弧の半径または円錐曲線の rho 値
		 *
		 *  @a radius で丸みが作れない場合、この関数は
		 *  丸みの半径を min(矩形の辺の長さ) * 0.5 として計算する。
		 */
		bool create(
			const MGRect* rect,
			double        radius
			);
		
		void draw(mgSysGL& sgl) const;
		MGCurve* release();
		bool valid() const;

	private:
		std::unique_ptr<MGCurve>  m_roundRect;
	};

} // namespace mgcalc

#endif // __MGCALC_RECT_H__
