using MessagePack;
namespace EarthQuake.Core.Animation;
///
/// 線形補間された波の半径を保存するクラス
///
///
[MessagePackObject]
public class InterpolatedWaveData
{
[Key("radius")] public float[] Radius { get; init; } = [];
[Key("wave")] public Dictionary Waves { get; init; } = [];
private float GetRadius(int depth, float seconds, bool isPWave)
{
if (!Waves.TryGetValue(depth, out var values)) return 0;
if (seconds <= (isPWave ? values[0].PTime : values[0].STime)) return 0;
switch (values.Length)
{
case 0:
{
return 0;
}
case 1:
{
return 0;
}
default:
{
if (seconds <= values[0].PTime) return 0;
for (var i = 0; i < values.Length - 1; i++)
{
if (isPWave)
{
if (!(values[i].PTime <= seconds) || !(seconds <= values[i + 1].PTime)) continue;
var t = (seconds - values[i].PTime) / (values[i + 1].PTime - values[i].PTime);
return Radius[i] * (1 - t) + Radius[i + 1] * t;
}
else
{
if (!(values[i].STime <= seconds) || !(seconds <= values[i + 1].STime)) continue;
var t = (seconds - values[i].STime) / (values[i + 1].STime - values[i].STime);
return Radius[i] * (1 - t) + Radius[i + 1] * t;
}
}
return isPWave
? (values[^1].PTime - seconds) * (Radius[^1] - Radius[^2]) + Radius[^2]
: (values[^1].STime - seconds) * (Radius[^1] - Radius[^2]) + Radius[^2];
}
}
}
///
/// P波の半径を取得する
///
/// 震源の深さ
/// 経過時間
/// 半径
public float GetPRadius(int depth, float seconds) => GetRadius(depth, seconds, true) / Earth * 360;
///
/// S波の半径を取得する
///
/// 震源の深さ
/// 経過時間
/// 半径
public float GetSRadius(int depth, float seconds) => GetRadius(depth, seconds, false) / Earth * 360;
private const int Earth = 40075;
}
///
/// P波、S波の時間軸を保存するクラス
///
[MessagePackObject]
public class PSWave
{
[Key(0)] public float PTime { get; init; }
[Key(1)] public float STime { get; init; }
}