/*------------------------------------------------------------------------------*
 * File Name: 				 													*
 * Creation: 																	*
 * Purpose: OriginC Source C file												*
 * Copyright (c) ABCD Corp.	2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010		*
 * All Rights Reserved															*
 * 																				*
 * Modification Log:															*
 * Zachary 07/25/06 ADD_GET_INTERPOLATED_XZ_YZ_CURVES_FROM_3D_DATA_FUNCTION		*
 * Arvin 07/26/06 ADD_XYZ_GRIDDING_NAG											*
 * Zachary 08/23/06 EXTRAPOLATION_ASLO_PERMITTED_FOR_GET_CURVES					*
 * Cloud 04/14/08 QA70-10497 REMOVE_DUPLICATE_DATA_TO_AVOID_NAG_CRASH			*
 * Kyle 12/02/2008 REMOVE_MISSING_DATA_IN_VECTOR_X_AND_Y_BEFORE_GRIDDING		*
 * Kyle 02/19/2009 QA80-13136 OUTPUT_OUR_OWN_MESSAGE_FOR_NAG_ERROR				*
 * Kyle 02/23/2009 FIX_RUNTIME_ERROR_WHILE_CALLING_NAG_FUNCTIONS				*
 * Kyle 02/26/2009 CENTRALIZE_CODE_TO_TRIM_INDEPENDENT							*
 *------------------------------------------------------------------------------*/
 
////////////////////////////////////////////////////////////////////////////////////
// Including the system header file Origin.h should be sufficient for most Origin
// applications and is recommended. Origin.h includes many of the most common system
// header files and is automatically pre-compiled when Origin runs the first time.
// Programs including Origin.h subsequently compile much more quickly as long as
// the size and number of other included header files is minimized. All NAG header
// files are now included in Origin.h and no longer need be separately included.
//
// Right-click on the line below and select 'Open "Origin.h"' to open the Origin.h
// system header file.
#include <Origin.h>
////////////////////////////////////////////////////////////////////////////////////


////////////////////////////////////////////////////////////////////////////////////
#include <OC_nag8.h>	//CPY 7/26/06
#include <Nag_utils.h>
#include <wks2mat.h> //Cloud 04/14/08 QA70-10497 REMOVE_DUPLICATE_DATA_TO_AVOID_NAG_CRASH
#include <ocu.h>		///Kyle 02/19/2009 QA80-13136 OUTPUT_OUR_OWN_MESSAGE_FOR_NAG_ERROR
////////////////////////////////////////////////////////////////////////////////////
// Start your functions here.



/// Zachary 07/25/06 ADD_GET_INTERPOLATED_XZ_YZ_CURVES_FROM_3D_DATA_FUNCTION
/// this function is mostly used in surface fitting parameters initialization.
/// Fisher 2008-10-7 QA80-12334 IMPROVE_SPEED_FOR_SURFACE_FITTING
//bool get_interpolated_xz_yz_curves_from_3D_data( Curve& x_curve , Curve& y_curve, const vector& x_data, const vector& y_data, const vector& z_data,)
bool get_interpolated_xz_yz_curves_from_3D_data( Curve& x_curve , Curve& y_curve, const vector& x_data, const vector& y_data, const vector& z_data, int bAutoReduceSize)
/// End IMPROVE_SPEED_FOR_SURFACE_FITTING
{
	
#define VEC_SIZE 50

	Curve x_z_curve(x_data, z_data);
	Curve y_z_curve(y_data, z_data);

	Nag_2d_Scat_Method method = Nag_RC;
	Nag_Scat_Struct comm;
	NagError fail;

	fail.code = NE_NOERROR;
	fail.print = 0;

	/// Cloud 04/14/08 QA70-10497 REMOVE_DUPLICATE_DATA_TO_AVOID_NAG_CRASH
	// nag_2d_scat_interpolant
	//int a = NE_NOERROR;
	//e01sac(method, x_data.GetSize(), x_data, y_data, z_data, &comm, NULL, &fail);
	vector vx_data, vy_data, vz_data;
	
	/// Fisher 2008-10-7 QA80-12334 IMPROVE_SPEED_FOR_SURFACE_FITTING
	//vx_data = x_data;
	//vy_data = y_data;
	//vz_data = z_data;
	//int nSize = ocmath_xyz_remove_duplicates(vx_data.GetSize(), vx_data, vy_data, vz_data);
	//e01sac(method, nSize, vx_data, vy_data, vz_data, &comm, NULL, &fail);
	double dx1, dx2, dy1, dy2;
	int nSize, nSizeRaw = x_data.GetSize();
	if( bAutoReduceSize )
	{
		int nExamineMethod = ocmath_xyz_examine_data_ex(nSizeRaw, x_data, y_data, z_data);
		if(Examine_XYZ_Regular == nExamineMethod || Examine_XYZ_Sparse == nExamineMethod)
		{
			#define N 32
			vx_data.SetSize(N*N);
			vy_data.SetSize(N*N);
			vz_data.SetSize(N*N);
			nSize = reduce_3D_data_size(x_data, y_data, z_data, nSizeRaw, vx_data, vy_data, vz_data, N, N);
			if(nSize < 10)
				bAutoReduceSize = false;
			else
				e01sac(Nag_Shep, nSize, vx_data, vy_data, vz_data, &comm, NULL, &fail);
		}
		else
			bAutoReduceSize = false;
		
	}
	
	if(!bAutoReduceSize)		// Old way
	{
		vx_data = x_data;
		vy_data = y_data;
		vz_data = z_data;
		nSize = ocmath_xyz_remove_duplicates(nSizeRaw, vx_data, vy_data, vz_data);
		e01sac(method, nSize, vx_data, vy_data, vz_data, &comm, NULL, &fail);
	}
	/// End IMPROVE_SPEED_FOR_SURFACE_FITTING

	/// End REMOVE_DUPLICATE_DATA_TO_AVOID_NAG_CRASH
	if (fail.code != NE_NOERROR && fail.code != NW_VALUE_EXTRAPOLATED ) //Zachary 08/23/06 EXTRAPOLATION_ASLO_PERMITTED_FOR_GET_CURVES
//	if (fail.code != NE_NOERROR )
	{
		printf("%s\n", fail.message);
		nag_2d_scat_free(&comm);
		return false;
	}

	double dxMin, dxMax, dyMin, dyMax;
	x_data.GetMinMax(dxMin, dxMax);
	y_data.GetMinMax(dyMin, dyMax);
	vector vX(VEC_SIZE), vY(VEC_SIZE), vZ(VEC_SIZE);

	double coeff[3];
	fitpoly(x_z_curve, 2, coeff);
	vX.Data(dxMin, dxMax, (dxMax-dxMin)/(VEC_SIZE-1));
	vY = (coeff[2] < 0) ? xatymax(y_z_curve) : xatymin(y_z_curve);
	// nag_2d_scat_eval
	e01sbc(&comm, VEC_SIZE, vX, vY, vZ, &fail);
	if (fail.code != NE_NOERROR && fail.code != NW_VALUE_EXTRAPOLATED ) //Zachary 08/23/06 EXTRAPOLATION_ASLO_PERMITTED_FOR_GET_CURVES
//	if (fail.code != NE_NOERROR )
	{
		printf("%s\n", fail.message);
		return false;
	}

	Curve x_curve_temp(vX, vZ);
	x_curve.Create( x_curve_temp.GetSize() );
	if( !x_curve.IsValid() )
	{
		printf( "%s\n", "Error occurs during create curve!" );
		return false;
	}
	x_curve = x_curve_temp;
	
	vX = (coeff[2] < 0) ? xatymax(x_z_curve) : xatymin(x_z_curve);
	vY.Data(dyMin, dyMax, (dyMax-dyMin)/(VEC_SIZE-1));
	// nag_2d_scat_eval
	e01sbc(&comm, VEC_SIZE, vX, vY, vZ, &fail);
	if (fail.code != NE_NOERROR && fail.code != NW_VALUE_EXTRAPOLATED ) //Zachary 08/23/06 EXTRAPOLATION_ASLO_PERMITTED_FOR_GET_CURVES
//	if (fail.code != NE_NOERROR )
	{
		printf("%s\n", fail.message);
		return false;
	}
	//nag_2d_scat_free
	e01szc (&comm);

	Curve y_curve_temp(vY, vZ);
	y_curve.Create( x_curve_temp.GetSize() );
	if( !y_curve.IsValid() )
	{
		printf( "%s\n", "Error occurs during create curve!" );
		return false;
	}
	y_curve = y_curve_temp;
	
	return true;

#undef VEC_SIZE

return false;	
}
///End ADD_GET_INTERPOLATED_XZ_YZ_CURVES_FROM_3D_DATA_FUNCTION

///Arvin 07/26/06 ADD_XYZ_GRIDDING_NAG
int xyz_gridding_nag(const vector& vx, const vector& vy, const vector& vz, const vector& vxGrid, const vector& vyGrid, matrix& mat, const int& nMethod, const int& nq, const int& nw) 
{
	///Kyle 12/02/2008 REMOVE_MISSING_DATA_IN_VECTOR_X_AND_Y_BEFORE_GRIDDING
	vector vXGrid, vYGrid, vZGrid;
	vXGrid = vx;
	vYGrid = vy;
	vZGrid = vz;
	///Kyle 02/26/2009 CENTRALIZE_CODE_TO_TRIM_INDEPENDENT
	//vector<uint> vnXMissing, vnYMissing;
	//int nXMissing = vXGrid.Find(MATREPL_TEST_EQUAL, NANUM, vnXMissing);
	//int nYMissing = vYGrid.Find(MATREPL_TEST_EQUAL, NANUM, vnYMissing);
	//if(nXMissing || nYMissing)
	//{
		//vYGrid.Replace(vnXMissing, NANUM);
		//vXGrid.Replace(vnYMissing, NANUM);
		//vector<uint> vnMissing;
		//vYGrid.Find(MATREPL_TEST_EQUAL, NANUM, vnMissing);
		//vXGrid.Trim();
		//vYGrid.Trim();
		//for(int ii = vnMissing.GetSize()-1; ii>=0; ii--)
			//vZGrid.RemoveAt(vnMissing[ii]);
	//}
	trim_independent(vXGrid, vYGrid, vZGrid);
	///End CENTRALIZE_CODE_TO_TRIM_INDEPENDENT
	///END REMOVE_MISSING_DATA_IN_VECTOR_X_AND_Y_BEFORE_GRIDDING

	Nag_2d_Scat_Method  method;
	Nag_Scat_Struct  comm;
	NagError  fail;
	Nag_E01_Opt optional;
	//INIT_FAIL
	fail.code = NE_NOERROR;
	fail.print = 0;
	if(nMethod == RANDOM_SHEPARD_METHOD)
	{
		method = Nag_Shep;
		optional.nq = nq;
		optional.nw = nw;
		optional.rnq = -1.0;
	}
	else
	{
		method = Nag_RC;
		//optional = NULL;
	}
	///Kyle 12/02/2008 REMOVE_MISSING_DATA_IN_VECTOR_X_AND_Y_BEFORE_GRIDDING
	//int nSize = vx.GetSize();
	int nSize = vXGrid.GetSize();
	///End REMOVE_MISSING_DATA_IN_VECTOR_X_AND_Y_BEFORE_GRIDDING
	int nRows = mat.GetNumRows();
	int nCols = mat.GetNumCols();
	//nag_2d_scat_interpolan
	///Kyle 12/02/2008 REMOVE_MISSING_DATA_IN_VECTOR_X_AND_Y_BEFORE_GRIDDING
	//e01sac(method, nSize, vx, vy, vz, &comm, &optional, &fail);	
	///Kyle 02/23/2009 FIX_RUNTIME_ERROR_WHILE_CALLING_NAG_FUNCTIONS
	//e01sac(method, nSize, vXGrid, vYGrid, vZGrid, &comm, &optional, &fail);	
	try{
		e01sac(method, nSize, vXGrid, vYGrid, vZGrid, &comm, &optional, &fail);	
	}catch(int nErr)
	{
		string strErrMsg;
		strErrMsg.Format(_L("Error from e01sac: %d"), nErr);
		warning_msg_box(strErrMsg, false);
		return nErr;
	}
	///End FIX_RUNTIME_ERROR_WHILE_CALLING_NAG_FUNCTIONS
	///End REMOVE_MISSING_DATA_IN_VECTOR_X_AND_Y_BEFORE_GRIDDING
	if (fail.code != NE_NOERROR)
	{
		///Kyle 02/19/2009 QA80-13136 OUTPUT_OUR_OWN_MESSAGE_FOR_NAG_ERROR
		// for now only NE_DATA_NOT_UNIQUE use our own error message
		//printf("Error from e01sac: %s\n", fail.message);
		string strErrMsg;
		switch(fail.code)
		{
		case NE_DATA_NOT_UNIQUE:
			ocu_load_msg_str(ERR_DUPLICATES_XY_PAIRS_IN_GRIDDING, &strErrMsg);		//"Gridding failed. Duplicate XY pairs found. Please try to modify the \"Replace Duplicates With\" option first."
			break;
		default:
			strErrMsg.Format(_L("Error from e01sac: %s"), fail.message);
			break;
		}
		warning_msg_box(strErrMsg, false);
		///End OUTPUT_OUR_OWN_MESSAGE_FOR_NAG_ERROR
		//nag_2d_scat_free
		e01szc(&comm);
		return fail.code;
	}
	///Kyle 02/23/2009 FIX_RUNTIME_ERROR_WHILE_CALLING_NAG_FUNCTIONS
	////nag_2d_scat_eval 	
	//e01sbc(&comm, nRows*nCols, vxGrid, vyGrid, mat, &fail);
	////nag_2d_scat_free
	//e01szc(&comm);
	try{
		e01sbc(&comm, nRows*nCols, vxGrid, vyGrid, mat, &fail);
	}catch(int nErr)
	{
		string strErrMsg;
		strErrMsg.Format(_L("Error from e01sbc: %d"), nErr);
		warning_msg_box(strErrMsg, false);
		return nErr;
	}
	try{
		e01szc(&comm);
	}catch(int nErr)
	{
		string strErrMsg;
		strErrMsg.Format(_L("Error from e01szc: %d"), nErr);
		warning_msg_box(strErrMsg, false);
		return nErr;
	}
	///End FIX_RUNTIME_ERROR_WHILE_CALLING_NAG_FUNCTIONS
	if (fail.code != NE_NOERROR && fail.code != NW_VALUE_EXTRAPOLATED)
	{
		printf("Error from e01sbc: %s\n", fail.message);
		return fail.code;
	}
	
	return OE_NOERROR;	
}
///end Arvin 07/26/06 ADD_XYZ_GRIDDING_NAG
