/********************************************************************/
/* Copyright (c) 2019 System fugen G.K. and Yuzi Mizuno          */
/* All rights reserved.                                             */
/********************************************************************/
//! @file
//!	@brief  Declaration for class MGIgesPD120.
//!	@author System fugen

#include "StdAfx.h"
#include "mgiges/IgesIfstream.h"
#include "mgiges/IgesGsec.h"
#include "mgiges/IgesPD120.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

using namespace MGIges;
//!	@brief MGIgesPD120 is the class for Iges parameter data type 120(Surface of Revolution).

// Constructors.

//! Constructs an object of class MGIgesPD120.
MGIgesPD120::MGIgesPD120(MGIgesDirectoryEntry* DEpointer)
:MGIgesPD(SURFACE_OF_REVOLUTION,DEpointer), m_axis_of_revolution_DE(0),m_generatrix_DE(0),
m_start_angle(0.), m_terminate_angle(0.){
}

//Read in parameter data from string stream data.
void MGIgesPD120::read_in(
	char pDelimeter,
	std::istringstream& pdstream
){
	get_DEpointer(pDelimeter,pdstream,m_axis_of_revolution_DE);
	get_DEpointer(pDelimeter,pdstream,m_generatrix_DE);
	MGCL::get_real(pDelimeter,pdstream,m_start_angle);
	MGCL::get_real(pDelimeter,pdstream,m_terminate_angle);
}

//Write out this PD as MGIgesParamLine's(into plines).
//Except for string data, one integer or double data is output
//into one MGIgesParamLine, not striding over more than one line.
//Only when string data is output(to Holleris string), the data
//may stride over more than one lines.
//plines[i] for 0<=i<plines.size() are valid.
void MGIgesPD120::write_out_into_string(
	const MGIgesGSec& gsec,	//Input gsec to input delimeter_param and delimeter_record;
	std::vector<std::string>& plines ///<output plines.
)const{
	put_DEpointer(m_axis_of_revolution_DE,gsec,plines);
	put_DEpointer(m_generatrix_DE,gsec,plines);
	put_real(m_start_angle,gsec,plines);
	put_real(m_terminate_angle,gsec,plines);
}

//Convert de(type=120: Ruled surface) to MGSurface.
//Returned is a newed object.
MGSurface* MGIgesIfstream::convert_revolution_surface(
	const MGIgesDirectoryEntry& de
)const{
	const std::unique_ptr<MGIgesPD>& pd=de.paramData();
	const MGIgesPD120* pd120=static_cast<const MGIgesPD120*>(pd.get());
	int axisDE=pd120->m_axis_of_revolution_DE;
	std::unique_ptr<MGGel> obj1=std::unique_ptr<MGGel>(convert_to_gel(axisDE));
	MGStraight* axisp=dynamic_cast<MGStraight*>(obj1.get());
	if(!axisp)
		return 0;
	std::unique_ptr<MGStraight> axis=std::unique_ptr<MGStraight>(dynamic_cast<MGStraight*>(obj1.release()));

	int generatrixDE=pd120->m_generatrix_DE;
	std::unique_ptr<MGGel> obj2=std::unique_ptr<MGGel>(convert_to_gel(generatrixDE));
	MGCurve* generatrixp=dynamic_cast<MGCurve*>(obj2.get());
	if(!generatrixp)
		return 0;

	std::unique_ptr<MGCurve> generatrix=std::unique_ptr<MGCurve>(dynamic_cast<MGCurve*>(obj2.release()));
	MGTransf tr;
	tr.set_rotate_3D(axis->direction(),pd120->m_start_angle,axis->root_point());
	(*generatrix)*=tr;

	double sa=pd120->m_start_angle, ta=pd120->m_terminate_angle;
	double angle=ta - sa;
	std::unique_ptr<MGRSBRep> surf=MGCL::create_revolved_surface(*generatrix, *axis, angle);
	surf->exchange_uv();surf->negate(0);
	surf->change_range(false,sa,ta);

	/////////////**********DEBUGWRITE
//	const MGSPointSeq& sp=surf->surface_bcoef();
//	const MGKnotVector& tu=surf->knot_vector_u();
//	const MGKnotVector& tv=surf->knot_vector_v();
//	if(tu.bdim()==2 && tv.bdim()==9){
//		if(-3.1818<tu(0) && tu(0)<-3.1816 &&
//			1.823<tu(2) && tu(2)<1.824 &&
//			-.001<tv(0) && tv(0)<.001 &&
//			18.848<tv(9) && tv(9)<18.85 &&
//			1619.403<sp(0,0,0) && 1619.405>sp(0,0,0) &&
//			1527.402<sp(1,8,2) && 1527.404>sp(1,8,2))
//			std::cout<<sp<<std::endl;
//	}/////////////**********DEBUGWRITE

	return surf.release();
}
