// 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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 //
//////////////////////////////////////////////////////////////////////