📄 xgraphdataserie.cpp
字号:
double fSum = 0.0;
TDataPoint* pData;
pData = new TDataPoint[m_nCount];
pData[0].fXVal = m_pData[0].fXVal;
pData[0].fYVal = m_pData[0].fYVal;
for ( int i = 1; i < m_nCount; i++ )
{
p = min(i, span);
if ( p <= span )
{
fSum = 0.0;
for ( int y = 0; y < p; y++ )
fSum += m_pData[i-y].fYVal;
}
else
fSum = fSum - m_pData[i-p].fYVal + m_pData[i].fYVal;
pData[i].fYVal = fSum / (double) p;
pData[i].fXVal = m_pData[i].fXVal;
}
return pData;
}
TDataPoint* CXGraphDataSerie::GetExponentialMovingAverage(int span)
{
double se = 2.0 / ((double)span + 1.0);
double le = 1.0 - se;
TDataPoint* pData;
pData = new TDataPoint[m_nCount];
pData[0].fXVal = m_pData[0].fXVal;
pData[0].fYVal = m_pData[0].fYVal;
for ( int i = 1; i < m_nCount; i++ )
{
pData[i].fYVal = m_pData[i].fYVal * se + pData[i-1].fYVal * le;
pData[i].fXVal = m_pData[i].fXVal;
}
return pData;
}
TDataPoint* CXGraphDataSerie::GetLinearMovingAverage(int span)
{
TDataPoint* pData;
double fSum = 0.0;
double fDiv = 0.0;
int p;
pData = new TDataPoint[m_nCount];
pData[0].fXVal = m_pData[0].fXVal;
pData[0].fYVal = m_pData[0].fYVal;
for ( int i = 1; i < m_nCount; i++ )
{
fSum = 0.0;
p = min(i, span);
if ( p <= span )
{
fDiv = 0.0;
for ( int y = 1; y <= p; y++ )
fDiv += (double) y;
}
for ( int y = 0; y < p; y++ )
fSum += m_pData[i-y].fYVal * (p - y);
pData[i].fYVal = fSum / fDiv;
pData[i].fXVal = m_pData[i].fXVal;
}
return pData;
}
inline double W_BARTLETT(double n, double k, double d = 1.0)
{
return (n == 0) ? 0 : (d * (1 - fabs((k - 0.5 * n) / (0.5 * n))));
}
TDataPoint* CXGraphDataSerie::GetTriangularMovingAverage(int span)
{
TDataPoint* pData;
double fSum = 0.0;
double fDiv = 0.0;
int p;
pData = new TDataPoint[m_nCount];
pData[0].fXVal = m_pData[0].fXVal;
pData[0].fYVal = m_pData[0].fYVal;
for ( int i = 1; i < m_nCount; i++ )
{
fSum = 0.0;
p = min(i, span);
if ( p <= span )
{
fDiv = 0.0;
for ( int y = 1; y <= p; y++ )
fDiv += W_BARTLETT(p+1, y, p);
}
for ( int y = 1; y <= p; y++ )
fSum += m_pData[i-y+1].fYVal * W_BARTLETT(p+1, y, p);
pData[i].fYVal = fSum / fDiv;
pData[i].fXVal = m_pData[i].fXVal;
}
return pData;
}
TDataPoint* CXGraphDataSerie::GetSineWeightedMovingAverage(int span)
{
TDataPoint* pData;
double fSum = 0.0;
double fDiv = 0.0;
double d = 0.0;
double f = _PI / (double) (span + 1);
int p;
pData = new TDataPoint[m_nCount];
pData[0].fXVal = m_pData[0].fXVal;
pData[0].fYVal = m_pData[0].fYVal;
for ( int i = 1; i < m_nCount; i++ )
{
fSum = 0.0;
p = min( i, span );
for ( int y = 0; y < p; y++ )
fSum += sin((double)(p - y) * f) * m_pData[i-y].fYVal;
if ( i <= span )
{
d = 0.0;
for ( int y = 1; y <= p; y++ )
d += sin((double) y * f);
}
pData[i].fYVal = fSum / d;
pData[i].fXVal = m_pData[i].fXVal;
}
return pData;
}
BOOL CXGraphDataSerie::HitTestLine(POINT pt0, POINT pt1, POINT ptMouse, int nWidth)
{
VECTOR2D tt0, tt1;
double dist;
int nHalfWidth;
//
//Get the half width of the line to adjust for hit testing of wide lines.
//
nHalfWidth = (nWidth/2 < 1) ? 1 : nWidth/2;
//
//Convert the line into a vector using the two endpoints.
//
POINTS2VECTOR2D(pt0, pt1, tt0);
//Convert the line from the left endpoint to the mouse point into a vector.
//
POINTS2VECTOR2D(pt0, ptMouse, tt1);
//
//Obtain the distance of the point from the line.
//
dist = vDistFromPointToLine(&pt0, &pt1, &ptMouse);
//
//Return TRUE if the distance of the point from the line is within the width
//of the line
//
BOOL bRet = (dist >= -nHalfWidth && dist <= nHalfWidth);
return bRet;
}
void CXGraphDataSerie::Serialize( CArchive& archive )
{
int nHelper;
CXGraphObject::Serialize (archive);
if( archive.IsStoring() )
{
archive << m_nCount;
archive.Write (m_pData, sizeof(TDataPoint) * m_nCount);
archive << m_nFirstVisible;
archive << m_nLastVisible;
archive << m_nXAxis;
archive << m_nYAxis;
archive << m_nIndex;
archive << m_nLineSize;
archive << m_nFillStyle;
archive << m_nMarkerType;
archive << m_nMarker;
archive << m_nMarkerSize;
archive << m_nLineStyle;
archive << m_bShowMarker;
archive << m_bFillBeneath;
archive << m_bFillTransparent;
archive << m_nFillCurve;
archive << m_crFillColor;
archive << m_cLabel;
nHelper = (int) m_gtType;
archive << nHelper;
}
else
{
archive >> m_nCount;
m_bAutoDelete = true;
m_pData = new TDataPoint[m_nCount];
archive.Read (m_pData, sizeof(TDataPoint) * m_nCount);
archive >> m_nFirstVisible;
archive >> m_nLastVisible;
archive >> m_nXAxis;
archive >> m_nYAxis;
archive >> m_nIndex;
archive >> m_nLineSize;
archive >> m_nFillStyle;
archive >> m_nMarkerType;
archive >> m_nMarker;
archive >> m_nMarkerSize;
archive >> m_nLineStyle;
archive >> m_bShowMarker;
archive >> m_bFillBeneath;
archive >> m_bFillTransparent;
archive >> m_nFillCurve;
archive >> m_crFillColor;
archive >> m_cLabel;
archive >> nHelper;
m_gtType = (EGraphType) nHelper;
}
}
/////////////////////////////////////////////////////////////////
bool CPolynomialSolver::Solve(double a[], double b[], int n)
{
for (int i = 0; i < n; i ++)
{
// find pivot
double mag = 0;
int pivot = -1;
for (int j = i; j < n; j ++)
{
double mag2 = fabs(a[i + j * n]);
if (mag2 > mag)
{
mag = mag2;
pivot = j;
}
}
// no pivot: error
if (pivot == -1 || mag == 0)
return false;
// move pivot row into position
if (pivot != i)
{
double temp;
for (int j = i; j < n; j ++)
{
temp = a[j + i * n];
a[j + i * n] = a[j + pivot * n];
a[j + pivot * n] = temp;
}
temp = b[i];
b[i] = b[pivot];
b[pivot] = temp;
}
// normalize pivot row
mag = a[i + i * n];
for (j = i; j < n; j ++) a[j + i * n] /= mag;
b[i] /= mag;
// eliminate pivot row component from other rows
for (int i2 = 0; i2 < n; i2 ++)
{
if (i2 == i) continue;
double mag2 = a[i + i2 * n];
for (int j = i; j < n; j ++)
a[j + i2 * n] -= mag2 * a[j + i * n];
b[i2] -= mag2 * b[i];
}
}
return true;
}
bool CPolynomialSolver::Polyfit(int nRows, int nOrder, TDataPoint *pData)
{
int rows = nRows;
int order = nOrder;
m_nGlobalO = order;
double *base = new double[order * rows];
double *alpha = new double[order * order];
double *alpha2 = new double[order * order];
double *beta = new double[order];
// calc base
for (int i = 0; i < order; i ++)
{
for (int j = 0; j < rows; j ++)
{
int k = i + j * order;
base[k] = i == 0 ? 1.0 : pData[j].fXVal * base[k - 1];
}
}
// calc alpha2
for (i = 0; i < order; i ++)
{
for (int j = 0; j <= i; j ++)
{
double sum = 0.0;
for (int k = 0; k < rows; k ++)
{
int k2 = i + k * order;
int k3 = j + k * order;
sum += base[k2] * base[k3];
}
int k2 = i + j * order;
alpha2[k2] = sum;
if (i != j)
{
k2 = j + i * order;
alpha2[k2] = sum;
}
}
}
// calc beta
for (int j = 0; j < order; j ++)
{
double sum = 0;
for (int k = 0; k < rows; k ++)
{
int k3 = j + k * order;
sum += pData[k].fYVal * base[k3];
}
beta[j] = sum;
}
// get alpha
for (j = 0; j < order * order; j ++)
alpha[j] = alpha2[j];
// solve for params
bool bRes = Solve(alpha, beta, order);
for (j = 0; j < order; j ++)
m_fC[j] = beta[j];
delete base;
delete beta;
delete alpha;
delete alpha2;
return bRes;
}
double CPolynomialSolver::GetValue(double fX)
{
double fRes = 0.0;
for (int i = 0; i < m_nGlobalO; i++)
fRes += (m_fC[i] * pow(fX, i));
return fRes;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -