From cc3c7199c0c56376c67caf5a9ca21fe5854238a9 Mon Sep 17 00:00:00 2001
From: tian <11429339@qq.com>
Date: Sat, 13 Jun 2026 18:18:19 +0800
Subject: [PATCH] =?UTF-8?q?refactor:=20CloudExpansionModel=E6=8F=90?=
=?UTF-8?q?=E5=8F=96RoundsNeeded/TimeToDensity/TimeToReach?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- RadiusAt/DensityAt/TimeToReach/TimeToDensity/RoundsNeeded 放入独立模块
- CalcRoundsNeeded 委托给 cloudModel.RoundsNeeded(requiredCoverage)
- GenerateFireEventsAt expansionTime 用 cloudModel.TimeToReach(RadiusAt(30f))
- 147/150 (Piston hp=0.10边际,LongRoute校验)
---
.../Algorithms/CloudExpansionModel.cs | 20 +++++++++++++++++++
.../Algorithms/DefaultDefensePlanner.cs | 16 ++++++---------
2 files changed, 26 insertions(+), 10 deletions(-)
diff --git a/src/CounterDrone.Core/Algorithms/CloudExpansionModel.cs b/src/CounterDrone.Core/Algorithms/CloudExpansionModel.cs
index b35c34e..86aa15a 100644
--- a/src/CounterDrone.Core/Algorithms/CloudExpansionModel.cs
+++ b/src/CounterDrone.Core/Algorithms/CloudExpansionModel.cs
@@ -49,6 +49,26 @@ namespace CounterDrone.Core.Algorithms
return volume > 0.001f ? (float)_ammo.SourceStrength / volume : (float)_ammo.CoreDensity;
}
+ /// 达到指定浓度所需时间(密度随膨胀下降,较晚时间密度更低)
+ /// 浓度首次低于threshold的时间(s),如果不会低于则返回MaxDuration
+ 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);
+ }
+
+ /// 覆盖指定距离需要的云团数量(间距=2R)
+ public int RoundsNeeded(float requiredCoverage)
+ {
+ float R = RadiusAt(30f);
+ float spacing = 2f * R;
+ return Math.Max(1, (int)Math.Ceiling(requiredCoverage / spacing));
+ }
+
/// 达到指定半径所需时间 (s)
public float TimeToReach(float radius)
{
diff --git a/src/CounterDrone.Core/Algorithms/DefaultDefensePlanner.cs b/src/CounterDrone.Core/Algorithms/DefaultDefensePlanner.cs
index 41d3861..cfcdcff 100644
--- a/src/CounterDrone.Core/Algorithms/DefaultDefensePlanner.cs
+++ b/src/CounterDrone.Core/Algorithms/DefaultDefensePlanner.cs
@@ -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();
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;