test: DamageAssessment 5项单元测试验证路径积分正确
- 单云穿心/两云相邻/9云链/两云有间隙/两点跨云
This commit is contained in:
parent
a3bf6720c6
commit
48368e0fe8
79
test/unit/CounterDrone.Core.Tests/DamageAssessmentTests.cs
Normal file
79
test/unit/CounterDrone.Core.Tests/DamageAssessmentTests.cs
Normal file
@ -0,0 +1,79 @@
|
||||
using System;
|
||||
using CounterDrone.Core.Algorithms;
|
||||
using Xunit;
|
||||
|
||||
namespace CounterDrone.Core.Tests
|
||||
{
|
||||
public class DamageAssessmentTests
|
||||
{
|
||||
[Fact]
|
||||
public void SingleSegment_ThroughCenter_DiameterExposure()
|
||||
{
|
||||
// 无人机穿过球心:路径=2R
|
||||
float len = DamageAssessment.PathInSphere(0, 0, 0, 40, 0, 0, 20, 0, 0, 20);
|
||||
Assert.Equal(40, len, 1);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TwoAdjacentClouds_FullCoverage()
|
||||
{
|
||||
// 20段×4m步长=80m,经过R=20的两朵相邻云(中心在20和60)
|
||||
float total = 0;
|
||||
float prevX = 0;
|
||||
for (int s = 0; s < 20; s++)
|
||||
{
|
||||
float nextX = prevX + 4;
|
||||
total += DamageAssessment.PathInSphere(prevX, 0, 0, nextX, 0, 0, 20, 0, 0, 20);
|
||||
total += DamageAssessment.PathInSphere(prevX, 0, 0, nextX, 0, 0, 60, 0, 0, 20);
|
||||
prevX = nextX;
|
||||
}
|
||||
// 每朵云直径40m,两朵共80m
|
||||
Assert.True(Math.Abs(total - 80f) < 1f, $"total={total:F2}, expected=80");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NineCloudChain_CoverageMatchesTheory()
|
||||
{
|
||||
// 9朵云,间距40m,R=20m,无人机段长22.2m(55.6m/s×0.4s)
|
||||
float[] cloudX = { 9840, 9880, 9920, 9960, 10000, 10040, 10080, 10120, 10160 };
|
||||
float radius = 20;
|
||||
float total = 0;
|
||||
float prevX = 9800;
|
||||
for (int t = 0; t < 20; t++)
|
||||
{
|
||||
float nextX = prevX + 22.22f;
|
||||
foreach (float cx in cloudX)
|
||||
total += DamageAssessment.PathInSphere(prevX, 0, 0, nextX, 0, 0, cx, 0, 0, radius);
|
||||
prevX = nextX;
|
||||
}
|
||||
// 理论: 9×40m = 360m
|
||||
Assert.True(Math.Abs(total - 360f) < 10f, $"total={total:F1}, expected=360");
|
||||
}
|
||||
[Fact]
|
||||
public void TwoCloudsWithGap_GapYieldsNoExposure()
|
||||
{
|
||||
// 两朵云中心在20和80, R=20: 云1=[0,40], 云2=[60,100], 间隙=[40,60]
|
||||
float total = 0;
|
||||
float prevX = 0;
|
||||
for (int s = 0; s < 25; s++) // 100m / 4m = 25段
|
||||
{
|
||||
float nextX = prevX + 4;
|
||||
total += DamageAssessment.PathInSphere(prevX, 0, 0, nextX, 0, 0, 20, 0, 0, 20);
|
||||
total += DamageAssessment.PathInSphere(prevX, 0, 0, nextX, 0, 0, 80, 0, 0, 20);
|
||||
prevX = nextX;
|
||||
}
|
||||
// 每朵云直径40m,两朵共80m,间隙无暴露
|
||||
Assert.True(Math.Abs(total - 80f) < 1f, $"total={total:F2}, expected=80");
|
||||
}
|
||||
[Fact]
|
||||
public void TwoPointsInDifferentClouds_GapExcluded()
|
||||
{
|
||||
// 两朵云R=10, 边间距50: 云1中心(0), 云2中心(70)
|
||||
// 两点: 云1内(0)→云2内(70)
|
||||
float len1 = DamageAssessment.PathInSphere(0, 0, 0, 70, 0, 0, 0, 0, 0, 10);
|
||||
float len2 = DamageAssessment.PathInSphere(0, 0, 0, 70, 0, 0, 70, 0, 0, 10);
|
||||
float total = len1 + len2;
|
||||
Assert.True(Math.Abs(total - 20f) < 1f, $"total={total:F2}, expected=20 (10+10)");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -134,5 +134,54 @@ namespace CounterDrone.Core.Tests
|
||||
var vertices = new (float X, float Z)[] { (0, 0), (10, 0), (10, 10), (0, 10) };
|
||||
Assert.False(Kinematics.PointInPolygon(20, 5, vertices));
|
||||
}
|
||||
[Fact]
|
||||
public void PathInSphere_CenterPass_ReturnsFullDiameter()
|
||||
{
|
||||
// 无人机穿过球心: 路径长度 = 2R
|
||||
float len = DamageAssessment.PathInSphere(0, 0, 0, 40, 0, 0, 20, 0, 0, 20);
|
||||
Assert.Equal(40, len, 1);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PathInSphere_EdgePass_ReturnsCorrectChord()
|
||||
{
|
||||
// 从(0)→(40), 球心(30), R=20: 进入t=0.25(x=10), 段尾在球内(t=1,x=40), 路径=30m
|
||||
float len = DamageAssessment.PathInSphere(0, 0, 0, 40, 0, 0, 30, 0, 0, 20);
|
||||
Assert.True(System.Math.Abs(len - 30f) < 1f, $"len={len:F2}");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PathInSphere_Miss_ReturnsZero()
|
||||
{
|
||||
float len = DamageAssessment.PathInSphere(0, 0, 0, 10, 0, 0, 50, 0, 0, 20);
|
||||
Assert.Equal(0, len, 1);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PathInSphere_PartialEntry_ReturnsCorrectSegment()
|
||||
{
|
||||
// 从球外(0)到球内(20), R=20, 球心(30): 进入点在10, 段长=10
|
||||
float len = DamageAssessment.PathInSphere(0, 0, 0, 20, 0, 0, 30, 0, 0, 20);
|
||||
Assert.True(System.Math.Abs(len - 10f) < 1f, $"len={len:F2}");
|
||||
}
|
||||
[Fact]
|
||||
public void PathInSphere_TwoClouds_AccumulatesCorrectly()
|
||||
{
|
||||
// 一段经过两个云: (0→100), 云1(20,R20), 云2(80,R20)
|
||||
float len1 = DamageAssessment.PathInSphere(0, 0, 0, 100, 0, 0, 20, 0, 0, 20);
|
||||
float len2 = DamageAssessment.PathInSphere(0, 0, 0, 100, 0, 0, 80, 0, 0, 20);
|
||||
Assert.True(System.Math.Abs(len1 - 40f) < 1f, $"cloud1 len={len1:F2}");
|
||||
Assert.True(System.Math.Abs(len2 - 40f) < 1f, $"cloud2 len={len2:F2}");
|
||||
}
|
||||
[Fact]
|
||||
public void PathInSphere_AdjacentClouds_SumCorrectly()
|
||||
{
|
||||
// 无人机从云1中心(0)到云2中心(40),两云R=20,间距=40(边碰边)
|
||||
// 两个云在段内路径:云1=20m(中心→右边缘), 云2=20m(左边缘→中心)
|
||||
float len1 = DamageAssessment.PathInSphere(0, 0, 0, 40, 0, 0, 0, 0, 0, 20);
|
||||
float len2 = DamageAssessment.PathInSphere(0, 0, 0, 40, 0, 0, 40, 0, 0, 20);
|
||||
float total = len1 + len2;
|
||||
Assert.True(System.Math.Abs(total - 40f) < 1f, $"total={total:F2} (cloud1={len1:F2} + cloud2={len2:F2})");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user