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;