99 lines
4.5 KiB
C#
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;
|
|
}
|
|
}
|
|
}
|