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

/**
 * @file editfunc.h
 * @brief EditCmd 系で共通で利用する機能を宣言しておく。
 *
 * 目的は、ツールクラスの cpp から純粋に計算処理部を分離することだ。
 * 後々別モジュール化しやすくなるはず。
 */
#pragma once

class MGGelPositions;
class MGGroup;
class MGObject;
class MGPosition;
class MGPickObject;
class MGPickObjects;
class MGVector;

class MGCommandBase;
class fugenView;

/// 仮想交差オプション有効時の切断オブジェクト投影方向を決める。
/// @param[in] c_or_p 切断オブジェクト
/// @param[in] pView トリムイベントが発生したビュー
/// @param[in] bApparentIntersection 仮想交差を有効にするか
/// @return 投影方向が求まれば、その方向。
/// @throws 特別な例外は投げない。
///
/// 投影方向は分割コマンドと同様のルールで決定し、UI 側から計算側
/// (MGCL) に指示すること。
///
/// -# 仮想交差が ON の場合、投影方向をビュー直とする。
/// -# トリムイベントが平行ビューで発生した場合、切断オブジェクト
///    が曲線または点ならばをビュー直方向に投影する。
/// -# トリムイベントが透視図ビューで発生し、かつ切断オブジェクトが平面曲線である場合、
///    切断曲線を曲線平面に対して垂直な方向へ投影する。
/// -# それ以外の場合、オブジェクトの投影方向を MGCL が計算する「面直方向」とする。
MGVector GetObjProjDir(
	const MGObject& c_or_p,
	const fugenView* pView,
	bool bApparentIntersection);

/// 曲線延長タイプ
/// @see ExtendNaive
enum ExtendType
{
	START, ///< 始点側を延長する
	END, ///< 終点側を延長する
	BOTH, ///< 始点側と終点側を延長する
};

/// 曲線の両端をとにかく延長して新しい曲線を返す。
/// @param[in] curve 曲線
/// @param[in] dExtend 延長部分の長さ
/// @param[in] type 延長タイプ
/// @return 延長した曲線を返す。
/// @throws 特別な例外は投げない。
///
/// @pre dExtend > MGTolerance::wc_zero
///
/// @a curve が延長できない形状の場合は、戻り値は元と同じ形状となる。
/// いずれにせよ戻り値は new したオブジェクトであり、呼び出し側で
/// delete する必要がある。
///
/// @a curve が直線の場合、延長の長さを無限とする。
MGCurve* ExtendCurveNaive(
	const MGCurve& curve,
	double dLength,
	ExtendType type);

/// ピック曲線を複数のピックオブジェクトでトリムする。
/// @param[in] trimmee トリムターゲット曲線
/// @param[in] Ctrimmers 切断曲線群
/// @param[in] Strimmers 切断サーフェス群
/// @param[in] pView トリムイベントが発生したビュー
/// @param[in] bExtendCutters 切断曲線群を延長するか
/// @param[in] bApparentIntersection 仮想交差を有効にするか
/// @param[in,out] cmd コマンド（実際はドキュメントを処理）
/// @param[in] bExtract トリムではなく抽出を行う
/// @return トリムが確定してドキュメントに変更が入ったら true を返す。
/// @throws 特別な例外は投げない。
///
/// @note 旧 MGTrimTool::trim_curve
bool ExecTrimCurve(
	MGPickObject& trimmee,
	const MGPickObjects& Ctrimmers,
	const MGPickObjects& Strimmers,
	const fugenView* pView,
	bool bExtendCutters,
	bool bApparentIntersection,
	MGCommandBase& cmd,
	bool bExtract = false);

/// ピックサーフェスを複数のピックオブジェクトでトリムする。
/// @param[in] surface surface to trim (trimmee).
/// @param[in] Ctrimmers 切断曲線群
/// @param[in] Strimmers 切断サーフェス群
/// @param[in] dir projection direction to project @a Ctrimmers onto the surface.
/// @param[in] bExtendCutters 切断曲線群を延長するか
/// @param[in,out] cmd コマンド（実際はドキュメントを処理）
/// @param[in] bExtract トリムではなく抽出を行う
/// @return トリムが確定してドキュメントに変更が入ったら true を返す。
/// @throws 特別な例外は投げない。
///
/// @note 旧 MGTrimTool::trim_fsurface
bool ExecTrimFSurf(
	MGPickObject& surface,
	const MGPickObjects& Ctrimmers,
	const MGPickObjects& Strimmers,
	const MGVector& dir,
	bool bExtendCutters,
	MGCommandBase& cmd,
	bool bExtract = false);

/// 分割コマンド実行（交点・交線による）
/// @param[in,out] target 分割処理の対象要素（曲線かサーフェスか）
/// @param[in,out] cutter 切断位置を決めるための要素群
/// @param[in,out] cmd コマンド（実際はドキュメントを処理）
/// @return 曲線分割後のパーツの個数
/// @throws 特別な例外は投げない。
size_t ExecSplitByIntersection(
	MGPickObjects& target,
	const MGPickObjects& cutter,
	MGCommandBase& cmd);

/// 補助関数
/// @param[in,out] target 分割処理の対象曲線
/// @param[in,out] params 分割位置の曲線パラメータ。
///    呼び出し後、内容が後はソートされている。
/// @param[in,out] parent
/// @return 
MGGelPositions ExecSplitCurveByParam(
	MGPickObject& target,
	std::vector<double>& params,
	MGGroup* parent);

/// 補助関数
/// @param[in,out] target 分割処理の対象サーフェス
/// @param[in,out] curves 分割位置を決める曲線群
/// @param[in,out] parent
/// @return 
MGGelPositions ExecSplitSurfByCurve(
	MGPickObject& target,
	const std::vector<const MGCurve*>& curves,
	MGGroup* parent);

/// 分割コマンド実行（曲線をロケート点で）
/// @param[in,out] target 分割処理の対象曲線
/// @param[in,out] params 分割位置の曲線パラメータ。
///    呼び出し後、内容が後はソートされている。
/// @param[in,out] cmd コマンド（実際はドキュメントを処理）
/// @return 曲線分割後のパーツの個数
/// @throws 特別な例外は投げない。
///
/// @note 旧 MGSplitTool::SplitCurveByPoints
///
/// @bug 閉曲線の分割では「端点」を含むセグメントが抽出できていない。
size_t ExecSplitCurveByPoints(
	MGPickObject& target,
	std::vector<double>& params,
	MGCommandBase& cmd);

/// 分割コマンド実行（サーフェスをアイソカーブで）
/// @param[in,out] target 分割処理の対象サーフェス
/// @param[in,out] uparams 分割位置の U 一定アイソカーブ
/// @param[in,out] vparams 分割位置の V 一定アイソカーブ
/// @param[in,out] cmd コマンド（実際はドキュメントを処理）
/// @return サーフェス分割後のパーツの個数
/// @throws 特別な例外は投げない。
size_t ExecSplitSurfByIsocurves(
	MGPickObject& target,
	std::vector<bool>& paramKinds,
	std::vector<double>& params,
	MGCommandBase& cmd);
