Files
2024-02-22 14:52:53 -05:00

115 lines
4.2 KiB
C#

using System;
using System.Collections;
namespace MarketData.Numerical
{
// The column is the key, the row is the value.
// For Time series elements put the date in the column and the value in the row
public class Element
{
private double row;
private double column;
public Element()
{
}
public Element(double column, double row)
{
this.column = column;
this.row = row;
}
public double Row
{
get { return row; }
set { row = value; }
}
public double Column
{
get { return column; }
set { column = value; }
}
}
public class CatmullRom
{
private CatmullRom()
{
}
public static bool PerformSpline(Element[] sourcePairs, Element[] destPairs)
{
double a0, a1, a2, a3;
double dx, dx1, dx2;
double dy, dy1, dy2;
double endPointOne;
double endPointTwo;
double resamplingPos;
double xPoint;
int clampOne, clampTwo;
int direction;
int destSize = destPairs.Length;
int sourceSize = sourcePairs.Length;
int inputIndex, index;
a0 = a1 = a2 = a3 = endPointOne = 0;
if (sourceSize < 2 || destSize < 1) return false;
if (((Element)sourcePairs[0]).Column < ((Element)sourcePairs[1]).Column)
{
if (((Element)destPairs[0]).Column < ((Element)sourcePairs[0]).Column ||
((Element)destPairs[destSize - 1]).Column > ((Element)sourcePairs[sourceSize - 1]).Column)
direction = 0;
else direction = 1;
}
else
{
if (((Element)destPairs[0]).Column > ((Element)sourcePairs[0]).Column ||
((Element)destPairs[destSize - 1]).Column < ((Element)sourcePairs[sourceSize - 1]).Column)
direction = 0;
else direction = -1;
}
if (0 == direction) return false;
if (1 == direction) endPointTwo = ((Element)destPairs[0]).Column - 1;
else endPointTwo = ((Element)destPairs[0]).Column + 1;
for (index = 0; index < destSize; index++)
{
resamplingPos = ((Element)destPairs[index]).Column;
if ((1 == direction && resamplingPos > endPointTwo) ||
(-1 == direction && resamplingPos < endPointTwo))
{
for (inputIndex = 0; inputIndex < sourceSize && resamplingPos > ((Element)sourcePairs[inputIndex]).Column; inputIndex++) ;
if (resamplingPos < ((Element)sourcePairs[inputIndex]).Column) inputIndex--;
if (inputIndex < 0) inputIndex = 0;
else if (inputIndex == sourceSize-1) inputIndex--;
endPointOne = ((Element)sourcePairs[inputIndex]).Column;
endPointTwo = ((Element)sourcePairs[inputIndex + 1]).Column;
clampOne = Math.Max(inputIndex - 1, 0);
clampTwo = Math.Min(inputIndex + 2, sourceSize - 1);
double clampOneValue = ((Element)sourcePairs[clampOne]).Column;
double clampTwoValue = ((Element)sourcePairs[clampTwo]).Column;
dx = 1.0 / ((endPointTwo - endPointOne)==0?1:(endPointTwo-endPointOne));
dx1 = 1.0 / ((endPointTwo - clampOneValue) == 0 ? 1 : (endPointTwo - clampOneValue));
dx2 = 1.0 / (clampTwoValue-endPointOne == 0 ? 1 : (clampTwoValue - endPointOne));
dy = (((Element)sourcePairs[inputIndex + 1]).Row - ((Element)sourcePairs[inputIndex]).Row) * dx;
dy1 = (((Element)sourcePairs[inputIndex + 1]).Row - ((Element)sourcePairs[clampOne]).Row) * dx1;
dy2 = (((Element)sourcePairs[clampTwo]).Row - ((Element)sourcePairs[inputIndex]).Row) * dx2;
a0 = ((Element)sourcePairs[inputIndex]).Row;
a1 = dy1;
a2 = dx * (3 * dy - 2 * dy1 - dy2);
a3 = dx * dx * (-2 * dy + dy1 + dy2);
}
xPoint = resamplingPos - endPointOne;
((Element)destPairs[index]).Row = ((a3 * xPoint + a2) * xPoint + a1) * xPoint + a0;
}
return true;
}
public static Element[] CreateSplineSourceElements(double[] columns, double[] rows)
{
Element[] elements = new Element[columns.Length];
if (columns.Length != rows.Length) return null;
for (int index = 0; index < columns.Length; index++)
{
elements[index] = new Element(columns[index], rows[index]);
}
return elements;
}
}
} // namespace