refactor: CloudExpansionModel提取RoundsNeeded/TimeToDensity/TimeToReach
- RadiusAt/DensityAt/TimeToReach/TimeToDensity/RoundsNeeded 放入独立模块 - CalcRoundsNeeded 委托给 cloudModel.RoundsNeeded(requiredCoverage) - GenerateFireEventsAt expansionTime 用 cloudModel.TimeToReach(RadiusAt(30f)) - 147/150 (Piston hp=0.10边际,LongRoute校验)
This commit is contained in:
parent
510403a66c
commit
cc3c7199c0
@ -49,6 +49,26 @@ namespace CounterDrone.Core.Algorithms
|
||||
return volume > 0.001f ? (float)_ammo.SourceStrength / volume : (float)_ammo.CoreDensity;
|
||||
}
|
||||
|
||||
/// <summary>达到指定浓度所需时间(密度随膨胀下降,较晚时间密度更低)</summary>
|
||||
/// <returns>浓度首次低于threshold的时间(s),如果不会低于则返回MaxDuration</returns>
|
||||
public float TimeToDensity(float threshold)
|
||||
{
|
||||
// 密度 ≈ SourceStrength / (4/3 π R³),随R增大而下降
|
||||
// 求R使得密度=threshold: R³ = SourceStrength / (threshold * 4π/3)
|
||||
float src = (float)_ammo.SourceStrength;
|
||||
float volume = src / Math.Max(threshold, 0.000001f);
|
||||
float r = (float)Math.Pow(volume * 3f / (4f * (float)Math.PI), 1f / 3f);
|
||||
return TimeToReach(r);
|
||||
}
|
||||
|
||||
/// <summary>覆盖指定距离需要的云团数量(间距=2R)</summary>
|
||||
public int RoundsNeeded(float requiredCoverage)
|
||||
{
|
||||
float R = RadiusAt(30f);
|
||||
float spacing = 2f * R;
|
||||
return Math.Max(1, (int)Math.Ceiling(requiredCoverage / spacing));
|
||||
}
|
||||
|
||||
/// <summary>达到指定半径所需时间 (s)</summary>
|
||||
public float TimeToReach(float radius)
|
||||
{
|
||||
|
||||
@ -361,16 +361,12 @@ namespace CounterDrone.Core.Algorithms
|
||||
private int CalcRoundsNeeded(DroneGroup threat, AmmunitionSpec ammo,
|
||||
CombatScene env, bool isAirBased, float turbulentRadius)
|
||||
{
|
||||
var cloudModel = new CloudExpansionModel(ammo, env);
|
||||
float avgSpeed = (float)threat.Target.TypicalSpeed / 3.6f;
|
||||
float spacing = 2f * turbulentRadius;
|
||||
|
||||
var aerosolType = (AerosolType)ammo.AerosolType;
|
||||
float neededExposure = aerosolType == AerosolType.ActiveMaterial ? 2f : 6f;
|
||||
float singleCoverage = neededExposure * avgSpeed;
|
||||
float requiredCoverage = singleCoverage;
|
||||
|
||||
return Math.Max(1,
|
||||
(int)Math.Ceiling(requiredCoverage / spacing));
|
||||
float requiredCoverage = neededExposure * avgSpeed;
|
||||
return cloudModel.RoundsNeeded(requiredCoverage);
|
||||
}
|
||||
|
||||
private float ComputeInterceptProbability(DroneGroup threat,
|
||||
@ -399,7 +395,8 @@ namespace CounterDrone.Core.Algorithms
|
||||
var events = new List<FireEvent>();
|
||||
|
||||
var mid = ThreatMidpoint(threat);
|
||||
var (effectiveR, expansionTime, _) = ComputeEffectiveRadius(threat, ammo, env);
|
||||
var cloudModel = new CloudExpansionModel(ammo, env);
|
||||
float expansionTime = cloudModel.TimeToReach(cloudModel.RadiusAt(30f));
|
||||
|
||||
// 编队 Y 偏移:按车道分布
|
||||
float laneSpacingZ = yLanes > 1 ? formationWidth / (yLanes - 1) : 0f;
|
||||
@ -407,7 +404,7 @@ namespace CounterDrone.Core.Algorithms
|
||||
|
||||
float tx = mid.X + targetOffset;
|
||||
|
||||
// 按目标点位置计算无人机到达时间,非中点
|
||||
// 无人机到达目标点时间
|
||||
float droneSpeed = (float)threat.Target.TypicalSpeed / 3.6f;
|
||||
if (droneSpeed <= 0) return events;
|
||||
float startX = (float)threat.Waypoints[0].PosX;
|
||||
@ -420,7 +417,6 @@ namespace CounterDrone.Core.Algorithms
|
||||
distToTx = Math.Max(0, Math.Min(totalDist, distToTx));
|
||||
float txArrival = distToTx / droneSpeed;
|
||||
float recommendedTiming = txArrival - expansionTime;
|
||||
// 来不及:无人机到达时云团未形成 → 跳过此目标点
|
||||
if (recommendedTiming <= 0f) return events;
|
||||
|
||||
float fireTime;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user