/*------------------------------------------------------------------------------*
 *	File Name: 	ocTriContour.h									 						*
 *	Purpose:	triangular contour								   		*
 *				This header is used in VC ocMath DLL as well as in OC files		*
 *  Creation:	08/24/04, Soapy													* 
 *  	Copyright Originlab Corp.		2004, 2005								*
 *	Modification log	                                                        *
 *	RVD 10/28/2004 QA70-6954 v8.0146 TRI_CONTOUR_PLOT							*
 *  Soapy 11/03/2004 QA70-6954 ADD_BOUNDARY_NPTS_IN_OPEN_CONTOUR
 *  Soapy 11/24/04 QA70-6954 ADD_SETTINGS_TO_TRICONTOUR
 *	Soapy 03/10/05 QA70-6954 GET_SUPPLEMETARY_AREA_FOR_OPEN_CONTOUR				*
 *  Soapy 8/06/05 QA70-6954 SMOOTH_CONTOUR_BY_INTERPOLATION						*
 *  Fisher 3/11/08 CHANGE_TYPE_TO_CONST											*
 *	ML 3/19/2008 FIND_PEAKS_IF_NO_CLOSED_NO_NEED_TO_CLOSE_THEM					*
 *	Fisher 04/12/10 QA85-15305 BETTER_DATA_REDUCTION_METHOD_NEEDED_FOR_TRI_CONTOUR
 *	Fisher 05/07/10 ORG-107 TRI_CONTOUR_DATA_STRUCTURE_IMPROVEMENT				*
 *------------------------------------------------------------------------------*/
///Arvin  08/11/06  QA70-8891 CLEAN_UP_ERROR_CODE
/*------------------------------------------------------------------------------*
 *------------------CENTRALIZED ERROR CODES IN OCSCATINTP.CPP-------------------*
	enum{
		OE_NOERROR = 0,					//No errors were encountered
		OE_BAD_PARAM = 1,				//Bad values of parameters were inputed
		OE_DATA_ILL_CONDITIONED = 2,	//Ill conditioned datas were encountered
		OE_ALL_NODES_COLINEAR = 3,		//All nodes are on a single line
		OE_DATA_OUT_RANGE = 4,			//Datas are out of their reasonable range
		OE_NO_NEAREST_POINT = 5,		//Could not find the nearest point
		OE_AREA_EQUAL_ZERO = 6,			//AREA equals zero
		OE_DX_OR_DY_EQUAL_ZERO = 7,		//DX or DY equals zero
	};
*------------------------------------------------------------------------------*/
///end CLEAN_UP_ERROR_CODE

#ifndef _OC_TRI_CONTOUR
#define _OC_TRI_CONTOUR

#ifdef _MSC_VER	   //VC
	#ifdef OCMATH_EXPORTS
		#define OCMATH_API __declspec(dllexport)
	/// TD 06-19-2008 QA80-10844 TRICTR_IN_VIEWER
	#elif  defined(MIN_OK_VERSION)
		#define OCMATH_API
	/// end QA80-10844 TRICTR_IN_VIEWER
	#else
		#define OCMATH_API __declspec(dllimport)
	#endif
	extern "C" {
#else //_MSC_VER
	#define OCMATH_API
	#pragma dll(ocMath)	// Assoicate all functions below to ocMath.dll which must be in the Origin EXE folder
#endif	//!_MSC_VER 


typedef struct{
	int npts;
	double dZVal; // the contour level

	double *pCtX; // the points on the contour
	double *pCtY;

	int nSeg;   // the number of segment in pCtX and pCtY
	int *vSegEnd;  // the number of the last point in each segment
	///Soapy 11/03/2004 QA70-6954 ADD_BOUNDARY_NPTS_IN_OPEN_CONTOUR
	int *vBoundCount; // the number of boundary points using to close an open contour. 
	///END Soapy 11/03/2004 QA70-6954 ADD_BOUNDARY_NPTS_IN_OPEN_CONTOUR
	/// ML 3/19/2008 FIND_PEAKS_IF_NO_CLOSED_NO_NEED_TO_CLOSE_THEM
	int		numInfoAboutOpenContoursWhenClosingNotAsked;	//  size of pnInfoAboutOpenContoursWhenClosingNotAsked	
	int		*pnInfoAboutOpenContoursWhenClosingNotAsked;	// keeps the information about open/closed contours when TRI_CONTOURS_CLOSE not used (i.e. when closing not done)
	/// end FIND_PEAKS_IF_NO_CLOSED_NO_NEED_TO_CLOSE_THEM
}	CONTOURLINE;

///Soapy 11/24/04 QA70-6954 ADD_SETTINGS_TO_TRICONTOUR
// Settings of the contour returned by ocmath_tricontour()
enum
{
   TRI_CONTOURS_CLOSE   = 0x00010000,    // close open contours
   TRI_CONTOURS_PLUS_GRAD   = 0x00020000,    // close open contours such that +grad (CCW), otherwise -grad (CW)
   TRI_CONTOUR_AREA_EMPTY   = 0x00040000,    // area for empty contours
   TRI_CONTOUR_BOUNDS_CCW   = 0x00080000,    // boundary in CCW
   TRI_CONTOURS_DEFAULT  = TRI_CONTOURS_CLOSE|TRI_CONTOURS_PLUS_GRAD|TRI_CONTOUR_AREA_EMPTY    // default settings
};
///END ADD_SETTINGS_TO_TRICONTOUR

//Comments last updated by Forest on 03/23/05
/**
	Perform triangulation on the scatters.
Parameters:
	n = [Input]the number of scatters.
	x = [Input]the x position of the scatters.
	y = [Input]the x position of the scatters.
	f = [Input]the value of the scatters.
	strTriCnt = [Output]the resulted triangulation.
Return:
	0 on success or 
	-1: less than 3 points or all points collinear.
	-2: invalid array pointer or structure
See Also:
	ocmath_tricontour
*/
///Kevin 11/29/05 CHANGE_OCMATH_FUNCTION_TO_LOWER_CASE
//OCMATH_API int ocmath_Triangulation(int n, double *x, double *y, 
//				double *f, TRIANGULATION* strTriCnt);
// Fisher 3/11/08 CHANGE_VAR_TO_CONST
//OCMATH_API int ocmath_triangulation(int n, double *x, double *y, 
//									double *f, TRIANGULATION* strTriCnt);
OCMATH_API int ocmath_triangulation(int n, const double *x, const double *y, 
									const double *f, TRIANGULATION* strTriCnt);


//Comments last updated by Forest on 03/23/05
/**
	Obtain the contour curves on 1 contour level.
Parameters:
	dCL = [Input]the Z value of the contour level.
	strTriCnt = [Input]the triangulation structure output from ocmath_triangulation().
	strCL = [Output]the structure contains the contour curves.
	dwCntrl = Setting of the returned contour.
Example1:
	void test_ocmath_tricontour_ex1()
	{
		int i, j, m, nx, ny;
		double xhi, xlo, yhi, ylo;

		nx = 100;
		ny = 100;
		xlo = 0.0;
		ylo = 0.0;
		xhi = 1.0;
		yhi = 1.0;

		double x[10000], y[10000], f[10000];
		
		m = 0;
  		for (j=0; j<ny; ++j)
		{
			for (i=0; i<nx; ++i)
			{
				x[i+nx*j] = (1.0 * (nx-i-1) / (nx-1)) * xlo + (1.0*i / (nx-1)) * xhi;
				y[i+nx*j] = (1.0 * (ny-j-1) / (ny-1)) * ylo +	(1.0* j / (ny-1)) * yhi;
				f[m]= x[m]*x[m]-4*y[m] -y[m]*x[m];
				++m;
			}
		}
		
		TRIANGULATION strTriCnt;
		ocmath_triangulation(m, x, y, f, &strTriCnt);

		CONTOURLINE strCL;
		double vCL[4]={0.1, 0.5, 1, 1.5};
		for(int nCL = 0; nCL<4; nCL++)
		{
			ocmath_tricontour(vCL[nCL], &strTriCnt, &strCL);
			printf("\nContour Level: %f\n", vCL[nCL]);
			int nL = 0;
			for(i = 0; i<strCL.nSeg; i++)
			{
				for(j = nL; j<=strCL.vSegEnd[i]; j++)
				{
					double xx = strCL.pCtX[j];
					double yy = strCL.pCtY[j];
					printf("%f\t%f\t%f\n", xx, yy, xx*xx-4*yy -yy*xx);
				}

				printf("\n");
				nL = j;
			}
		}

		ocmath_triangulation_free(&strTriCnt);
		ocmath_tricontour_free(&strCL);
	}
Return:
	0 on success or -1 for invalid array pointer or structure.
*/
///Kevin 11/29/05 CHANGE_OCMATH_FUNCTION_TO_LOWER_CASE
//OCMATH_API int ocmath_TriContour(double dCL, TRIANGULATION* strTriCnt, CONTOURLINE *strCL, DWORD dwCntrl = TRI_CONTOURS_DEFAULT); ///Soapy 11/24/04 QA70-6954 ADD_SETTINGS_TO_TRICONTOUR
OCMATH_API int ocmath_tricontour(double dCL, TRIANGULATION* strTriCnt, CONTOURLINE *strCL, DWORD dwCntrl = TRI_CONTOURS_DEFAULT); ///Soapy 11/24/04 QA70-6954 ADD_SETTINGS_TO_TRICONTOUR
//Comments last updated by Forest on 03/23/05
/**
	Get the boundary points in sequence from the triangulation structure.
Parameters:
	strTriCnt = [Input]the triangulation structure;
	pn = [Output]pointer to the number of points on the boundary;
	pBx = [Output]pointers to the x position of the boundary points.
	pBy = [Output]pointers to the y position of the boundary points.
	pBf = [Output]pointers to the value of the boundary points.
	dwCntrl = boundary setting.
Example1:
	#include <ocTriContour.h>
	void triangulation_boundary_ex1()
	{
		int ii, jj, mm, nx, ny, n;
		double xhi, xlo, yhi, ylo;

		nx = 100;
		ny = 100;
		xlo = 0.0;
		ylo = 0.0;
		xhi = 1.0;
		yhi = 1.0;
		n = nx * ny;

		vector vx(n), vy(n), vf(n);
		
		mm = 0;
		for (jj=0; jj<ny; ++jj)
		{
			for (ii=0; ii<nx; ++ii)
			{
				vx[mm] = (1.0 * (nx-ii-1) / (nx-1)) * xlo + (1.0*ii / (nx-1)) * xhi;
				vy[mm] = (1.0 * (ny-jj-1) / (ny-1)) * ylo + (1.0* jj / (ny-1)) * yhi;
				vf[mm]= vx[mm]*vx[mm]-4*vy[mm] -vy[mm]*vx[mm];
				++mm;
			}
		}
		
		// Triangulate the data
		TRIANGULATION strTriCnt;
		ocmath_triangulation(mm, vx, vy, vf, &strTriCnt);

		// Get the boundary in counterclockwise
		int nBorder = strTriCnt.npb;
		vector vBX(nBorder), vBY(nBorder), vBF(nBorder);
		ocmath_triangulation_boundary(&strTriCnt, &nBorder, vBX, vBY, vBF);

		for(ii = 0; ii < nBorder; ii++)
		{
			printf("%f\t%f\t%f\n", vBX[ii], vBY[ii], vBF[ii]);
		}

		ocmath_triangulation_free(&strTriCnt);
	}
Example2:
	#include <ocTriContour.h>
	void triangulation_boundary_ex2()
	{
		Worksheet wks = Project.ActiveLayer();
		DataRange dr;
		dr.Add(wks, 0, "X"); 
		dr.Add(wks, 1, "Y");
		dr.Add(wks, 2, "Z");

		vector vx, vy, vz;
		dr.GetData(vx, 0);
		dr.GetData(vy, 1);
		dr.GetData(vz, 2);

		TRIANGULATION strTriCnt;
		ocmath_triangulation(vx.GetSize(), vx, vy, vz, &strTriCnt);

		int nBorder = strTriCnt.npb;
		vector vbx(nBorder), vby(nBorder), vbz(nBorder);
		ocmath_triangulation_boundary(&strTriCnt, &nBorder, vbx, vby, vbz);

		for(int ii = 0; ii < nBorder; ii++)
		{
			printf("%f\t%f\t%f\n", vbx[ii], vby[ii], vbz[ii]);
		}

		ocmath_triangulation_free(&strTriCnt);	
	}
Return:
	0 on success or -1 for invalid array pointer or structure.
*/
///Kevin 11/29/05 CHANGE_OCMATH_FUNCTION_TO_LOWER_CASE
//OCMATH_API int ocmath_Triangulation_Boundary(TRIANGULATION* strTriCnt, int* pn, double *pBx, double *pBy, double *pBf, DWORD dwCntrl = TRI_CONTOUR_BOUNDS_CCW);  ///Soapy 11/24/04 QA70-6954 ADD_SETTINGS_TO_TRICONTOUR
OCMATH_API int ocmath_triangulation_boundary(TRIANGULATION* strTriCnt, int* pn, double *pBx, double *pBy, double *pBf, DWORD dwCntrl = TRI_CONTOUR_BOUNDS_CCW);  ///Soapy 11/24/04 QA70-6954 ADD_SETTINGS_TO_TRICONTOUR
///Soapy 03/10/05 QA70-6954 GET_SUPPLEMETARY_AREA_FOR_OPEN_CONTOUR
//Comments last updated by Forest on 03/23/05
/**
	This function get the supplementary area defined by the open contour. 
	For example, if the area defined by the input contour is of +grad in CCW, 
	the output contour area will be of -grad in CW. Notice the function only
	works on open contours and the closed contours are not copied to the output
	contour structure.
Parameters:
	strTriCnt = [Input]the triangulation structure output from ocmath_triangulation()
	strCTIn = [Input]the original contour structure output from ocmath_tricontour()
	strCTOut = [Output]the result contour structure which contains the supplementary 
		area defined by the open contours.
	dwCntrl = [Input]the original setting when calling ocmath_tricontour().
Return:
	0 on success or
	-1 for invalid structure pointer or
	-2 for invalid triangulation or invalid contour data.
*/
///Kevin 11/29/05 CHANGE_OCMATH_FUNCTION_TO_LOWER_CASE
//OCMATH_API int ocmath_Triangulation_Supplementary_Area(TRIANGULATION* strTriCnt, const CONTOURLINE* strCTIn, CONTOURLINE* strCTOut, DWORD dwCntrl);
OCMATH_API int ocmath_triangulation_supplementary_area(TRIANGULATION* strTriCnt, const CONTOURLINE* strCTIn, CONTOURLINE* strCTOut, DWORD dwCntrl);
///END GET_SUPPLEMETARY_AREA_FOR_OPEN_CONTOUR

/// RVD 10/28/2004 QA70-6954 v8.0146 TRI_CONTOUR_PLOT
///Kevin 11/29/05 CHANGE_OCMATH_FUNCTION_TO_LOWER_CASE
//OCMATH_API void ocmath_Triangulation_init(TRIANGULATION *strTriCnt);
OCMATH_API void ocmath_triangulation_init(TRIANGULATION *strTriCnt);
//OCMATH_API void ocmath_TriContour_init(CONTOURLINE *strCL);
OCMATH_API void ocmath_tricontour_init(CONTOURLINE *strCL);
/// end TRI_CONTOUR_PLOT

/**
	Free the triangulation structure.
*/
///Kevin 11/29/05 CHANGE_OCMATH_FUNCTION_TO_LOWER_CASE
//OCMATH_API void ocmath_Triangulation_free(TRIANGULATION *strTriCnt);
OCMATH_API void ocmath_triangulation_free(TRIANGULATION *strTriCnt);

/**
	Free the contour structure.
*/
///Kevin 11/29/05 CHANGE_OCMATH_FUNCTION_TO_LOWER_CASE
//OCMATH_API void ocmath_TriContour_free(CONTOURLINE *strCL);
OCMATH_API void ocmath_tricontour_free(CONTOURLINE *strCL);

/**
	Copy the triangulation information from the structure to the arrays.
*/
///Kevin 11/29/05 CHANGE_OCMATH_FUNCTION_TO_LOWER_CASE
//OCMATH_API bool ocmath_Triangulation_to_array(TRIANGULATION* strTriCnt, double *pScat, int *pTri, int *pSide, int *pBorder);
OCMATH_API bool ocmath_triangulation_to_array(TRIANGULATION* strTriCnt, double *pScat, int *pTri, int *pSide, int *pBorder);

/**
	Construct the triangulation structure by the triangulation information stored in the arrays
*/
///Kevin 11/29/05 CHANGE_OCMATH_FUNCTION_TO_LOWER_CASE
//OCMATH_API bool ocmath_array_to_Triangulation(int np, double *pScat, int nt, int *pTri, int nl, int *pSide, int nb, int *pBorder, TRIANGULATION* strTriCnt);
OCMATH_API bool ocmath_array_to_triangulation(int np, double *pScat, int nt, int *pTri, int nl, int *pSide, int nb, int *pBorder, TRIANGULATION* strTriCnt);

/// RVD 10/28/2004 QA70-6954 v8.0146 TRI_CONTOUR_PLOT
/**
	linear interpolation of Z value for given X and Y using triangulation data
*/
///Kevin 11/29/05 CHANGE_OCMATH_FUNCTION_TO_LOWER_CASE
//OCMATH_API bool ocmath_Triangulation_value(TRIANGULATION* pTri, double x, double y, double& z);
OCMATH_API bool ocmath_triangulation_value(TRIANGULATION* pTri, double x, double y, double& z);
/// end TRI_CONTOUR_PLOT

///Soapy 8/06/05 QA70-6954 SMOOTH_CONTOUR_BY_INTERPOLATION
/**
	Smooth the contour line by cubic b-spline interpolation.
Parameter:
	strCT: Input - the contour line structure output from ocmath_tricontour(); Output - the smoothed contour line.
	nNoIntp: Input - the number of evaluated points in every 2 adjacent points on the original contour line.
	dCentripental: Input, the parameter using in the centripetal methodthe of curve parametrization, 0.5 by default. 
		It's the same of chord-length method when dCentripental = 1. It should be larger than zero.
Return:
	0 on success or -1 for invalid input parameter or NAG error codes.
*/
///Kevin 11/29/05 CHANGE_OCMATH_FUNCTION_TO_LOWER_CASE
//OCMATH_API int ocmath_TriContour_Smooth(CONTOURLINE* strCT, int nNoIntp, double dCentripental = 0.5);
OCMATH_API int ocmath_tricontour_smooth(CONTOURLINE* strCT, int nNoIntp, double dCentripental = 0.5);


/// Fisher	04/12/10 QA85-15305	BETTER_DATA_REDUCTION_METHOD_NEEDED_FOR_TRI_CONTOUR
OCMATH_API int ocmath_triangulation_reduce(int n, const double *x, const double *y, const double *f, TRIANGULATION* strTriCnt, int nSize = 500);
/// End BETTER_DATA_REDUCTION_METHOD_NEEDED_FOR_TRI_CONTOUR


/// Fisher 05/07/10 ORG-107 TRI_CONTOUR_DATA_STRUCTURE_IMPROVEMENT
OCMATH_API int	ocmath_tri_contour_interpolate(int nSize, double *pX, double *pY, double *pZ, const TRIANGULATION *pTri);
/// End TRI_CONTOUR_DATA_STRUCTURE_IMPROVEMENT

/// Fisher 05/12/10 ORG-97 XYZ_CONTOUR_PROFILE
OCMATH_API int ocmath_image_xyz_profile(
	TRIANGULATION	*pTriInfo,
	int nVertices, double* pxVertices, double* pyVertices,
	int nPoints,
	double* pxPoints,
	double* pyPoints,
	double* pIntensity,
	double* pError = NULL,
	int nWidth = 1,
	int iProjection = PROJECTION_NONE
);
/// ---------------

#ifdef _MSC_VER
	}
#endif	//_MSC_VER

#endif //_OC_TRI_CONTOUR