klhztrader/KLHZ.Trader.Core.Math/Declisions/Utils/ShapeAreaCalculator.cs

99 lines
4.5 KiB
C#

namespace KLHZ.Trader.Core.Math.Declisions.Utils
{
public static class ShapeAreaCalculator
{
// Метод для расчёта площади треугольника
public static double CalculateTriangleArea(
DateTime pointA_X, decimal pointA_Y,
DateTime pointB_X, decimal pointB_Y,
DateTime pointC_X, decimal pointC_Y)
{
// Определяем самую позднюю точку
DateTime latestPoint = new[] { pointA_X, pointB_X, pointC_X }.Max();
// Смещённые координаты
double offsetA = GetOffsetInSeconds(latestPoint, pointA_X);
double offsetB = GetOffsetInSeconds(latestPoint, pointB_X);
double offsetC = GetOffsetInSeconds(latestPoint, pointC_X);
// Расчёт расстояний
double sideAB = DistanceBetweenPoints(offsetA, (double)pointA_Y, offsetB, (double)pointB_Y);
double sideBC = DistanceBetweenPoints(offsetB, (double)pointB_Y, offsetC, (double)pointC_Y);
double sideCA = DistanceBetweenPoints(offsetC, (double)pointC_Y, offsetA, (double)pointA_Y);
// Формула Герона
double semiPerimeter = (sideAB + sideBC + sideCA) / 2;
return System.Math.Sqrt(semiPerimeter * (semiPerimeter - sideAB) *
(semiPerimeter - sideBC) * (semiPerimeter - sideCA));
}
// Метод для расчёта площади четырёхугольника
public static double CalculateQuadrilateralArea(
DateTime pointA_X, decimal pointA_Y,
DateTime pointB_X, decimal pointB_Y,
DateTime pointC_X, decimal pointC_Y,
DateTime pointD_X, decimal pointD_Y)
{
// Определяем самую позднюю точку
DateTime latestPoint = new[] { pointA_X, pointB_X, pointC_X, pointD_X }.Max();
// Смещённые координаты
double offsetA = GetOffsetInSeconds(latestPoint, pointA_X);
double offsetB = GetOffsetInSeconds(latestPoint, pointB_X);
double offsetC = GetOffsetInSeconds(latestPoint, pointC_X);
double offsetD = GetOffsetInSeconds(latestPoint, pointD_X);
// Суммируем площади двух треугольников
double firstTriangleArea = CalculateTriangleArea(pointA_X, pointA_Y, pointB_X, pointB_Y, pointD_X, pointD_Y);
double secondTriangleArea = CalculateTriangleArea(pointB_X, pointB_Y, pointC_X, pointC_Y, pointD_X, pointD_Y);
return firstTriangleArea + secondTriangleArea;
}
// Вспомогательные методы
// Конвертация разницы времён в секунды
private static double GetOffsetInSeconds(DateTime referencePoint, DateTime targetPoint)
{
return (referencePoint - targetPoint).TotalSeconds;
}
// Евклидово расстояние между двумя точками
private static double DistanceBetweenPoints(double x1, double y1, double x2, double y2)
{
return System.Math.Sqrt(System.Math.Pow(x2 - x1, 2) + System.Math.Pow(y2 - y1, 2));
}
public static bool TryGetAreasRelation(DateTime[] times, decimal[] values, decimal currentValue, TimeSpan boundTimeSpan, out double relation)
{
var upArea = 0d;
var downArea = 0d;
var startTime = times[times.Length - 1];
for (int i = 1; i < times.Length - 2; i++)
{
var k = values.Length - i;
if (startTime - times[k] > boundTimeSpan)
{
break;
}
var point = (double)(values[k] - currentValue);
var time = times[k];
var timePrev = times[k - 1];
var dt = (time - timePrev).TotalSeconds;
var ar = dt * point;
if (ar > 0)
{
upArea += ar;
}
else
{
downArea += System.Math.Abs(ar);
}
}
var area = downArea + upArea;
relation = area != 0 ? (double)upArea / area * 100 : 0;
return area != 0;
}
}
}