/*------------------------------------------------------------------------------*
 * 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:															*
 *  Will 06/24/2009 QA80-13783 CHANGE_PROTOTYPE_AND_ALGORITHM_FOR_EXAMINATION   *
 *	Sim 09-25-2009 QA80-13783 CHANGE_PROTOTYPE_AND_ALGORITHM_FOR_EXAMINATION	*
 *------------------------------------------------------------------------------*/
 
////////////////////////////////////////////////////////////////////////////////////
// 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 <oErrMsg.h>
#include <wks2mat.h>
#include <Nag_utils.h>
enum {	
		XYZ2MAT_METHOD_REGULAR, 
		XYZ2MAT_METHOD_SPARSE, 
		XYZ2MAT_METHOD_RANDOM_RENKA_CLINE, 
		XYZ2MAT_METHOD_RANDOM_SHEPARD, 
		XYZ2MAT_METHOD_RANDOM_TPS,
		XYZ2MAT_METHOD_RANDOM_KRIGING,
		//XYZ2MAT_METHOD_RANDOM_2D_BSPLINE,	///DG ADD_2D_B_SPLINE ///Leo 2006-2-11 2D_B_SPLINE_IS_REMOVED_DUE_TO_POOR_PERFORMANCE
		XYZ2MAT_METHOD_WEIGHTED_AVERAGE,	///Leo ADD_WEIGHTED_AVERAGE
};
////////////////////////////////////////////////////////////////////////////////////

int compute_surface_from_anchor_points(const vector& vX,const vector& vY,const vector& vZ,  int nRows, int nCols, matrix& mat)
{
	
	double dPrecision = 0.1;
	int nMethod = XYZ2MAT_METHOD_RANDOM_TPS;
	int nSize = vX.GetSize();

	double dxMin, dxStep, dyMin, dyStep, dxMax, dyMax;
	
	///---Sim 09-25-2009 QA80-13783 CHANGE_PROTOTYPE_AND_ALGORITHM_FOR_EXAMINATION
	//int nExamineMethod = ocmath_xyz_examine_data(nSize, vX, vY, vZ, dPrecision, NULL, &dxMin, &dxStep, &dxMax, &dyMin, &dyStep, &dyMax);
	int nExamineMethod = xyz_examine_data(nSize, vX, vY, vZ, dPrecision, NULL, &dxMin, &dxStep, &dxMax, &dyMin, &dyStep, &dyMax);
	///---End QA80-13783 CHANGE_PROTOTYPE_AND_ALGORITHM_FOR_EXAMINATION
	
	if (XYZ2MAT_METHOD_REGULAR == nMethod)
	{
		switch (nExamineMethod)
		{
		  case Examine_XYZ_Random:
		  	return CER_NOT_MATCHED_TRY_RANDOM_CONVERSION;
			  //MessageBox( GetWindow(),
			  //"XY data are not matched, try random conversion methods!\n",
			  //"Error",
			  //MB_OK | MB_ICONEXCLAMATION );
			  //return nExamineMethod;
			  
		  case Examine_XYZ_Sparse: 
		  	return CER_NOT_MATCHED_TRY_OTHER_CONVERSION;
			  //MessageBox( GetWindow(),
			  //"XY data are not matched, try sparse or random conversion methods!\n",
			  //"Error",
			  //MB_OK | MB_ICONEXCLAMATION );
			  //return nExamineMethod;
		}
	}
	///Arvin 08/15/06 CHECK_VALIDITY_OF_SPARSE_METHOD
	else if(XYZ2MAT_METHOD_SPARSE == nMethod)
	{
		switch (nExamineMethod)
		{
		  case Examine_XYZ_Random:
		  	return CER_NOT_MATCHED_TRY_RANDOM_CONVERSION;
			  //MessageBox( GetWindow(),
			  //"XY data are not matched, try random conversion methods!\n",
			  //"Error",
			  //MB_OK | MB_ICONEXCLAMATION );
			  //return nExamineMethod;
			  
		  case Examine_XYZ_Regular: 
		  	return CER_NOT_MATCHED_TRY_REGULAR_CONVERSION;
			  //MessageBox( GetWindow(),
			  //"XY data are not matched, try regular conversion methods!\n",
			  //"Error",
			  //MB_OK | MB_ICONEXCLAMATION );
			  //return nExamineMethod;
		}
	}


	vector vecZero(nRows*nCols);
	vecZero = 0;
	mat.SetByVector(vecZero);
	
	int iRet;
	
	switch(nMethod)
	{
		case XYZ2MAT_METHOD_REGULAR:
			iRet = ocmath_convert_regular_xyz_to_matrix(nSize, vX, vY, vZ, mat, dxMin, dxStep, nCols, dyMin, dyStep, nRows);
			return iRet;
	   	case XYZ2MAT_METHOD_SPARSE:
		   	iRet = ocmath_convert_sparse_xyz_to_matrix(nSize, vX, vY, vZ, mat, dxMin, dxStep,nCols, dyMin, dyStep, nRows, dPrecision);
			return iRet;
		default:
			break;
	}

	vector vxGrid(nRows*nCols), vyGrid(nRows*nCols);
	iRet = ocmath_mat_to_regular_xyz(NULL, nRows, nCols, dxMin, dxMax, dyMin, dyMax, vxGrid, vyGrid, NULL);
	if (iRet < 0) 
	{ 
		return iRet;
	}

	switch(nMethod)
	{
	   	case XYZ2MAT_METHOD_RANDOM_RENKA_CLINE:

           	iRet = xyz_gridding_nag(vX, vY, vZ, vxGrid, vyGrid, mat); 
           	return iRet;
		case XYZ2MAT_METHOD_RANDOM_SHEPARD:

			int nq = 12;
			int nw = 8;
        	int method = RANDOM_SHEPARD_METHOD;
        	iRet = xyz_gridding_nag(vX, vY, vZ, vxGrid, vyGrid, mat, method, nq, nw);
        	return iRet;
		case XYZ2MAT_METHOD_RANDOM_TPS:
			double tps_smooth = 0.1;
			ocmath_strTPS strTPS;
			ocmath_tps_initial(&strTPS);		
		   	double dReg;
		   	iRet = ocmath_tps_fit(nSize, vX, vY, vZ, tps_smooth, &strTPS, &dReg);
		   	if( iRet == 0 )
		   	{
				iRet = ocmath_tps_eval(nRows * nCols, vxGrid, vyGrid, mat, &strTPS);
		   	}
		   	ocmath_tps_free(&strTPS);
		   	return iRet;
	   case XYZ2MAT_METHOD_RANDOM_KRIGING:
			int min_pts = 3;
			double kriging_radius = 2;
			double kriging_smooth = 1.8;
			iRet = ocmath_2d_kriging_scat(nSize, vX, vY, vZ, min_pts, kriging_radius, kriging_smooth, nRows*nCols, vxGrid, vyGrid, mat);
			return iRet;
		case XYZ2MAT_METHOD_WEIGHTED_AVERAGE:			
			double average_radius = 2;
		  	iRet = ocmath_gridding_weighted_average(nSize, vX, vY, vZ, nRows*nCols, vxGrid, vyGrid, mat, average_radius, WEIGHTED_AVERAGE_SQUARE);
		  	return iRet; 
		default:
		  	break;
	}
	
	return 0;



}


////////////////////////////////////////////////////////////////////////////////////
// Include your own header files here.


////////////////////////////////////////////////////////////////////////////////////
// Start your functions here.