Click here to Skip to main content
15,878,959 members
Articles / Desktop Programming / MFC

CCurveDlg - Curve Interpolation

Rate me:
Please Sign up or sign in to vote.
2.75/5 (4 votes)
15 Sep 20012 min read 113.4K   5.3K   42  
A Photoshop-like curve dialog.
// CCurveDllImpl : implementation file
//
//
// Wrapper class for the XlXtrFun dll. Translates the c-style functions
// to C++ and MFC compatible functions. 
// XlXtrFun.xll (c) Scott Allen Rauch, Advanced Systems Design and Development, 
// 1993-1999. www.netrax.net/~jdavita/XlXtrFun.htm
//
// Copyright Johan Janssens, 2001 (jjanssens@mail.ru)
// Feel free to use and distribute. May not be sold for profit. 
//
// This code may be used in compiled form in any way you desire. This
// file may be redistributed unmodified by any means PROVIDING it is
// not sold for profit without the authors written consent, and
// providing that this notice and the authors name is included.
// If the source code in this file is used in any commercial application
// then acknowledgement must be made to the author of this file
// 
// This file is provided "as is" with no expressed or implied warranty.
// The author accepts no liability for any damage of buiness that this
// product may cause
//
// Please use and enjoy. Please let me know of any bugs/mods/improvements
// that you have found/implemented and I will fix/incorporate them into 
// this file 

#include "stdafx.h"
#include "CurveDllImpl.h"

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

HINSTANCE CCurveDllImpl::hDll = NULL;

//////////////////////////////////////////////////////////////////////
//Functions Defenitions
//////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////
//1D Numerical Functions

typedef unsigned long (CALLBACK* LPFNDLLLOOKUPCLOSESTVALUE)
	(double far*, unsigned long far*, double far*);

typedef unsigned long (CALLBACK* LPFNDLLINDEXOFCLOSESTVALUE)
	(double far*, unsigned long far*, double far*);

//////////////////////////////////////////////////////////////////////
//2D Numerical Functions

typedef unsigned long (CALLBACK* LPFNDLLSPLINE)
	(double far*,double far*, unsigned long far*, double far*, double far*);

typedef unsigned long (CALLBACK* LPFNDLLPFIT)
	(double far*,double far*, unsigned long far*, double far*, unsigned long far*, double far*);

typedef unsigned long (CALLBACK* LPFNDLLINTERP)
	(double far*, double far*, unsigned long far*, double far*, double far*);

typedef unsigned long (CALLBACK* LPFNDLLINTERPOLATE)
	(double far*, double far*, unsigned long far*, double far*, double far*, short far*, short far*, double far*);

typedef unsigned long (CALLBACK* LPFNDLLXATY)
	(double far*, double far*, unsigned long far*, short far*, double far*, double far*);

typedef unsigned long (CALLBACK* LPFNDLLDYDX)
	(double far*, double far*, unsigned long far*, double far*, double far*);

typedef unsigned long (CALLBACK* LPFNDLLDDYDX)
	(double far*, double far*, unsigned long far*, double far*, double far*);

//////////////////////////////////////////////////////////////////////
// Construction/Destruction                                         //
//////////////////////////////////////////////////////////////////////
CCurveDllImpl::CCurveDllImpl()
{
	hDll = LoadLibraryEx("XlXtrfun.dll", NULL, DONT_RESOLVE_DLL_REFERENCES);
	if (!hDll)
	{
	AfxMessageBox("Error: Cannot find component \"XlXtrFun.dll\"");
	}
}

CCurveDllImpl::~CCurveDllImpl()
{
	if(!FreeLibrary(hDll))
	{
		AfxMessageBox("Error : Cannot free library \"XlXtrFun.dll\"");
	}
}

//////////////////////////////////////////////////////////////////////
// CCurveDllImpl Functions											//
//////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////
//1D Numerical Functions											//
//////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////
//Description :
//  Returns the element in an array which is closest to a given value 
//   
//Function :
//   IndexOfClosestValue(Array of points, ValueToSeek)
//  
//    Array Of Points   CArray of points. The values must be either 
//                      constantly increasing or constantly decreasing.
//    ValueToSeek       Number. LookupClosestValue searches through all 
//                      the values in Array and returns the value in 
//                      Array which is closest to ValueToSeek.
//
//  Note that the first element of the array you give it is considered index = 1.

double CCurveDllImpl::LookupClosestValue(CArray<double, double>* arrayValues, double dValueToSeek)
{
	/*unsigned long __stdcall VBLookupClosestValue( double far * dArrayValues , 
		unsigned long far * npts , double far * ValueToSeek)*/

	LPFNDLLLOOKUPCLOSESTVALUE lpfnDllLookUpClosestValue = 
		(LPFNDLLLOOKUPCLOSESTVALUE) GetProcAddress(hDll, "VBLookUpClosestValue");
    ASSERT (lpfnDllLookUpClosestValue != NULL);

	unsigned long iSize = (unsigned long) arrayValues->GetSize();
	
	double arrValues[256];
	
	//extract data
	for(int i=0; i < (int) iSize; i++)
	{
		double dValue = arrayValues->GetAt(i);
		arrValues[i] = dValue;
	}

	//call functions
	double uValue = lpfnDllLookUpClosestValue(arrValues, &iSize, &dValueToSeek);

	return uValue;
}

///////////////////////////////////////////////////////////////////////
//Description :
//   Return the 1-based index of the closest value
//   
//Function :
//   IndexOfClosestValue(Array of points, ValueToSeek)
//  
//    Array Of Points   CArray of points. The values must be either 
//                      constantly increasing or constantly decreasing.
//    ValueToSeek       Number. IndexOfClosestValue searches through 
//                      all the values in Array and returns index of 
//                      the value in Array which is closest to ValueToSeek.
//
//  Note that the first element of the array you give it is considered index = 1.


double CCurveDllImpl::IndexOfClosestValue(CArray<double, double>* arrayValues, double dValueToSeek)
{
	/*unsigned long __stdcall VBLookupClosestValue( double far * dArrayValues , 
		unsigned long far * npts , double far * ValueToSeek)*/

	LPFNDLLINDEXOFCLOSESTVALUE lpfnDllIndexOfClosestValue = 
		(LPFNDLLINDEXOFCLOSESTVALUE) GetProcAddress(hDll, "VBIndexOfClosestValue");
    ASSERT (lpfnDllIndexOfClosestValue != NULL);

	unsigned long iSize = (unsigned long) arrayValues->GetSize();
	
	double arrValues[256];
	
	//extract data
	for(int i=0; i < (int) iSize; i++)
	{
		double dValue = arrayValues->GetAt(i);
		arrValues[i] = dValue;
	}

	//call functions
	double uIndex = lpfnDllIndexOfClosestValue(arrValues, &iSize, &dValueToSeek);

	return uIndex;
}

//////////////////////////////////////////////////////////////////////
//2D Numerical Functions											//
//////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////
//Description : 
//   Returns the Y at a given X on the natural cubic spline curve 
//   defined by a given set of points.
//
//Function : 
//    Spline(Array of points, GivenX)
//
//    Array Of Points   CArray of points. The values must be either 
//                      constantly increasing or constantly decreasing.
//    GivenX            Spline returns the Y at this X which is on 
//                      the natural cubic spline curve.

double CCurveDllImpl::Spline(CArray<CPoint, CPoint>* ptXY, double ptGivenX)
{
	/*unsigned long __stdcall VBSpline( double far * Xs , double far * Ys,
	  unsigned long far * npts , double far * X , double far * Y )*/
    
	LPFNDLLSPLINE lpfnDllSpline = (LPFNDLLSPLINE) GetProcAddress(hDll, "VBSpline");
    ASSERT (lpfnDllSpline != NULL);

	unsigned long iSize = (unsigned long) ptXY->GetSize();
	
	double Xs[256];
	double Ys[256];
	
	//extract data
	for(int i=0; i < (int) iSize; i++)
	{
		CPoint pt = ptXY->GetAt(i);
		Xs[i] = pt.x;
		Ys[i] = pt.y;
	}

	//call functions
	double ptReturnY;
	unsigned long uReturn = lpfnDllSpline(Xs, Ys, &iSize, &ptGivenX, &ptReturnY);

	return ptReturnY;
}

///////////////////////////////////////////////////////////////////////
//Description : 
//   Returns the Y at a given X on the polynomial curve of a given order 
//   least squares fit of data points in two dimensions.
//
//Function : 
//    PFit(Array of points, GivenX, Order)
//
//    Array Of Points   CArray of points. The values must be either 
//                      constantly increasing or constantly decreasing.
//    GivenX            PFit returns the Y at this X which is on the 
//                      polynomial fit curve.
//    Order             Integer indicating the order of the polynomial 
//                      used to fit the curve to the data.

double CCurveDllImpl::PFit(CArray <CPoint, CPoint>* ptXY, double ptGivenX, unsigned long PFitOrder)
{
	/*unsigned long _stdcall VBPFit(double far* Xs, double far* Ys, 
		unsigned long far* npts, double far* X, unsigned long far* l_nOrder, double far* Y);*/

	LPFNDLLPFIT lpfnDllPFit = (LPFNDLLPFIT) GetProcAddress(hDll, "VBPFit");
	ASSERT(lpfnDllPFit != NULL);

	unsigned long iSize = (unsigned long) ptXY->GetSize();

	double Xs[256];
	double Ys[256];

	//extract data
	for(int i=0; i < (int) iSize; i++)
	{
		CPoint pt = ptXY->GetAt(i);
		Xs[i] = pt.x;
		Ys[i] = pt.y;
	}

	//call functions
	double ptReturnY;
	unsigned long uReturn = lpfnDllPFit(Xs, Ys, &iSize, &ptGivenX, &PFitOrder, &ptReturnY);

	return ptReturnY;
}

///////////////////////////////////////////////////////////////////////
//Description : 
//   Returns the Y at a given X on the interpolated curve defined by a 
//   given set of points using the defaults of Interpolate.
//
//Function : 
//    Interp(Array of points, GivenX)
//
//    Array Of Points   CArray of points. The values must be either 
//                      constantly increasing or constantly decreasing.
//    GivenX            Interp returns the Y at this X which is on the 
//                      interpolate curve.

double CCurveDllImpl::Interp(CArray<CPoint, CPoint>* ptXY, double ptGivenX)
{
	/*unsigned long _stdcall VBInterpolate(double far* Xs, double far* Ys, 
		unsigned long far* npts, double far* X, double far* Y);*/

	LPFNDLLINTERP lpfnDllInterp = (LPFNDLLINTERP) GetProcAddress(hDll, "VBInterp");
	ASSERT(lpfnDllInterp != NULL);

	unsigned long iSize = (unsigned long) ptXY->GetSize();

	double Xs[256];
	double Ys[256];

	//extract data
	for(int i=0; i < (int) iSize; i++)
	{
		CPoint pt = ptXY->GetAt(i);
		Xs[i] = pt.x;
		Ys[i] = pt.y;
	}

	//call functions
	double ptReturnY;
	unsigned long uReturn = lpfnDllInterp(Xs, Ys, &iSize, &ptGivenX, &ptReturnY);

	return ptReturnY;
}

///////////////////////////////////////////////////////////////////////
//Description : 
//   Returns the Y at a given X on the interpolated curve defined by 
//   a given set of points.
//
//Function : 
//    Interpolate(Array of points, GivenX, Parabolic, Averaging, SmoothingPower)
//
//    Array Of Points   CArray of points. The values must be either 
//                      constantly increasing or constantly decreasing.
//    GivenX            Interpolate returns the Y at this X which is on t
//                      the interpolate curve.
//    Parabolic         Optional. Either TRUE of FALSE. If TRUE, Interpolate 
//                      develops a smooth "double parabolic" curve between the 
//                      given set of points. If FALSE, linear interpolation is used. 
//                      Default is TRUE.
//    Averaging         Optional. Either TRUE of FALSE. If TRUE, and Parabolic? = TRUE, 
//                      the interpolated curve is averaged from both directions for 
//                      curve smoothing (slope matching). If FALSE, and Parabolic? = TRUE, 
//                      for each interval, a parabola is created using the point 
//                      to the right and the two points to the left. 
//                      Default is TRUE.
//    SmoothingPower    Optional. The weight used for averaging is raised to this power. 
//                      Default is 1.


double CCurveDllImpl::Interpolate(CArray<CPoint, CPoint>* ptXY, double ptGivenX, short nParabolic, short nAveraging, double dPower)
{
	/*unsigned long _stdcall VBInterpolate(double far* Xs, double far* Ys, 
		unsigned long far* npts, double far* X, double far* Y, short far* Parabolic, short far* Averaging, double far* Power);*/

	LPFNDLLINTERPOLATE lpfnDllInterpolate = (LPFNDLLINTERPOLATE) GetProcAddress(hDll, "VBInterpolate");
	ASSERT(lpfnDllInterpolate != NULL);

	unsigned long iSize = (unsigned long) ptXY->GetSize();

	double Xs[256];
	double Ys[256];

	//extract data
	for(int i=0; i < (int) iSize; i++)
	{
		CPoint pt = ptXY->GetAt(i);
		Xs[i] = pt.x;
		Ys[i] = pt.y;
	}

	//call functions
	double ptReturnY;
	unsigned long uReturn = lpfnDllInterpolate(Xs, Ys, &iSize, &ptGivenX, &ptReturnY, &nParabolic, &nAveraging, &dPower);

	return ptReturnY;
}

///////////////////////////////////////////////////////////////////////
//Description : 
//   Returns the X value at the maximum (Peak), minimum (Valley), 
//   or given Y of an interpolated curve using the defaults of Interpolate. 
//   XatY is essentially the inverse of Interpolate.
//
//Function : 
//    XatY(Array of points, GivenY, SolveForType)
//
//    Array Of Points   CArray of points. The values must be either 
//                      constantly increasing or constantly decreasing.
//    GivenY            Ignored for PeakValleyOrY = Y, y, V or v; required 
//                      for PeakValleyOrY = Y or y. When PeakValleyOrY = Y or y, 
//                       XatY will return the X which yields the interpolated GivenY.
//	  SolveForType      PeakValleyOrY    Optional. Either P, p, V, v, Y, or y 
//                      indicating whether to return X at the interpolated maximum Y 
//                      (PeakValleyOrY = P or p for peak), minimum Y (PeakValleyOrY = V or v for valley), 
//                      or the interpolated X at a given Y (PeakValleyOrY = Y or y). 
//                      PeakValleyOrY must be a text value enclosed in quotation marks, 
//                      or a reference to a cell containing a text value. Default is P.


double CCurveDllImpl::XatY(CArray<CPoint, CPoint>* ptXY, double ptGivenY, short SolveForType)
{
	/* unsignde long_stdcall VBXatY (double far* Xs, double far* Ys, 
		unsigned long far* npts, short far* SolveForType, double far* GuessX, double far* YtoSeek)*/

	LPFNDLLXATY lpfnDllXatY = (LPFNDLLXATY) GetProcAddress(hDll, "VBXatY");
	ASSERT(lpfnDllXatY != NULL);

	unsigned long iSize = (unsigned long) ptXY->GetSize();

	double Xs[256];
	double Ys[256];

	//extract data
	for(int i = 0; i < (int) iSize; i++)
	{
		CPoint pt = ptXY->GetAt(i);
		Xs[i] = pt.x;
		Ys[i] = pt.y;
	}

	//call functions
	double ptGuessX;
	unsigned long uReturn = lpfnDllXatY(Xs, Ys, &iSize, &SolveForType, &ptGuessX, &ptGivenY);

	return ptGuessX;
}

///////////////////////////////////////////////////////////////////////
//Description : 
//   Returns the first derivative of the interpolated curve at the 
//    given X using the defaults of Interpolate.
//
//Function : 
//    DyDx(Array of points, GivenX)
//
//    Array Of Points   CArray of points. The values must be either 
//                      constantly increasing or constantly decreasing.
//    GivenX            DyDx returns the Y at this X which is on the 
//                      polynomial fit curve.

double CCurveDllImpl::DyDx(CArray<CPoint, CPoint>* ptXY, double ptGivenX)
{	
	/*unsigned long __stdcall VBdydx( double far * Xs , double far * Ys ,
	  unsigned long far * npts , double far * X , double far * YPrime )*/
    
	LPFNDLLDYDX lpfnDllDyDx = (LPFNDLLDYDX) GetProcAddress(hDll, "VBDydx");
    ASSERT (lpfnDllDyDx != NULL);

	unsigned long iSize = (unsigned long) ptXY->GetSize();
	
	double Xs[256];
	double Ys[256];
	
	//extract data
	for(int i=0; i < (int) iSize; i++)
	{
		CPoint pt = ptXY->GetAt(i);
		Xs[i] = pt.x;
		Ys[i] = pt.y;
	}

	//call functions
	double ptPrimeY;
	unsigned long uReturn = lpfnDllDyDx(Xs, Ys, &iSize, &ptGivenX, &ptPrimeY);

	return ptPrimeY;	
}

//////////////////////////////////////////////////////////////////////
//Description : 
//   Returns the second derivative of the interpolated curve at the 
//   given X using the defaults of Interpolate.
//
//Function : 
//    DyDx(Array of points, GivenX)
//
//    Array Of Points   CArray of points. The values must be either 
//                      constantly increasing or constantly decreasing.
//    GivenX            DDyDx returns the Y at this X which is on the 
//                      polynomial fit curve.

double CCurveDllImpl::DDyDx(CArray<CPoint, CPoint>* ptXY, double ptGivenX)
{	
	/*unsigned long __stdcall VBddydx( double far * Xs , double far * Ys ,
        long far * npts , double far * X , double far * YPrimePrime )*/
    
	LPFNDLLDDYDX lpfnDllDDyDx = (LPFNDLLDDYDX) GetProcAddress(hDll, "VBDDydx");
    ASSERT (lpfnDllDDyDx != NULL);

	unsigned long iSize = (unsigned long) ptXY->GetSize();
	
	double Xs[256];
	double Ys[256];
	
	//extract data
	for(int i=0; i < (int) iSize; i++)
	{
		CPoint pt = ptXY->GetAt(i);
		Xs[i] = pt.x;
		Ys[i] = pt.y;
	}

	//call functions
	double ptPrimePrimeY;
	unsigned long uReturn = lpfnDllDDyDx(Xs, Ys, &iSize, &ptGivenX, &ptPrimePrimeY);

	return ptPrimePrimeY;	
}

//////////////////////////////////////////////////////////////////////
//3D Numerical Functions

//////////////////////////////////////////////////////////////////////
//Low leven I/O Functions

//////////////////////////////////////////////////////////////////////
// CCurveDllImpl Implementation									//
//////////////////////////////////////////////////////////////////////

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
Russian Federation Russian Federation
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions