503 lines
33 KiB
C#
503 lines
33 KiB
C#
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||
using ThreatSource.Equipment;
|
||
using ThreatSource.Utils;
|
||
|
||
namespace ThreatSource.Tests.Equipment
|
||
{
|
||
[TestClass]
|
||
public class RcsPatternTests
|
||
{
|
||
// 此处理想情况下应与 RcsPattern.cs 中的常量匹配,或从该常量获取。
|
||
// 为测试目的,我们在此定义。如果 RcsPattern.DEFAULT_RCS_DBSM 发生更改,请确保此处保持一致。
|
||
private const double DEFAULT_RCS_DBSM_IN_PATTERN = 10.0;
|
||
private const double TEST_DELTA = 1e-6; // 浮点数比较的容差
|
||
|
||
/// <summary>辅助方法,用于创建具有可预测值的测试RCS矩阵。</summary>
|
||
/// <param name="rows">矩阵的行数。</param>
|
||
/// <param name="cols">矩阵的列数。</param>
|
||
/// <param name="valueFunc">用于生成值的函数。如果为null,则使用 (i * 10 + j + 1.0)。</param>
|
||
/// <returns>表示RCS矩阵的二维双精度浮点数组。</returns>
|
||
private double[,] CreateTestMatrix(int rows = 6, int cols = 4, Func<int, int, double>? valueFunc = null)
|
||
{
|
||
var matrix = new double[rows, cols];
|
||
if (valueFunc == null)
|
||
{
|
||
valueFunc = (r, c) => (r * 10 + c + 1.0);
|
||
}
|
||
|
||
for (int i = 0; i < rows; i++)
|
||
{
|
||
for (int j = 0; j < cols; j++)
|
||
{
|
||
matrix[i, j] = valueFunc(i, j);
|
||
}
|
||
}
|
||
return matrix;
|
||
}
|
||
|
||
[TestMethod]
|
||
public void DefaultConstructor_InitializesCorrectly()
|
||
{
|
||
var rcsPattern = new RcsPattern();
|
||
|
||
// Check RcsMatrixDataSource (List<List<double>>)
|
||
Assert.IsNotNull(rcsPattern.RcsMatrixDataSource, "RcsMatrixDataSource 不应该为 null。");
|
||
Assert.AreEqual(6, rcsPattern.RcsMatrixDataSource.Count, "RcsMatrixDataSource 应该有 6 行。");
|
||
for (int i = 0; i < 6; i++)
|
||
{
|
||
Assert.IsNotNull(rcsPattern.RcsMatrixDataSource[i], $"RcsMatrixDataSource 行 {i} 不应该为 null。");
|
||
Assert.AreEqual(4, rcsPattern.RcsMatrixDataSource[i].Count, $"RcsMatrixDataSource 行 {i} 应该有 4 列。");
|
||
for (int j = 0; j < 4; j++)
|
||
{
|
||
Assert.AreEqual(DEFAULT_RCS_DBSM_IN_PATTERN, rcsPattern.RcsMatrixDataSource[i][j], TEST_DELTA, $"RcsMatrixDataSource[{i}][{j}] 应该为默认值。");
|
||
}
|
||
}
|
||
|
||
// Check RcsMatrixData (double[,])
|
||
var rcsData = rcsPattern.RcsMatrixData;
|
||
Assert.IsNotNull(rcsData, "RcsMatrixData should not be null.");
|
||
Assert.AreEqual(6, rcsData.GetLength(0), "RcsMatrixData should have 6 rows.");
|
||
Assert.AreEqual(4, rcsData.GetLength(1), "RcsMatrixData should have 4 columns.");
|
||
for (int i = 0; i < 6; i++)
|
||
{
|
||
for (int j = 0; j < 4; j++)
|
||
{
|
||
Assert.AreEqual(DEFAULT_RCS_DBSM_IN_PATTERN, rcsData[i, j], TEST_DELTA, $"RcsMatrixData[{i},{j}] 应该为默认值。");
|
||
}
|
||
}
|
||
}
|
||
|
||
[TestMethod]
|
||
public void ParameterizedConstructor_WithValidMatrix_InitializesCorrectly()
|
||
{
|
||
double[,] expectedMatrix = CreateTestMatrix(); // 使用默认的6x4矩阵,其值为 (i*10+j+1)
|
||
|
||
var rcsPattern = new RcsPattern(expectedMatrix);
|
||
var actualMatrixData = rcsPattern.RcsMatrixData;
|
||
var actualMatrixDataSource = rcsPattern.RcsMatrixDataSource;
|
||
|
||
// 检查 RcsMatrixData (double[,])
|
||
Assert.AreEqual(6, actualMatrixData.GetLength(0));
|
||
Assert.AreEqual(4, actualMatrixData.GetLength(1));
|
||
for (int i = 0; i < 6; i++)
|
||
{
|
||
for (int j = 0; j < 4; j++)
|
||
{
|
||
Assert.AreEqual(expectedMatrix[i, j], actualMatrixData[i, j], TEST_DELTA, $"RcsMatrixData[{i},{j}] 没有匹配预期。");
|
||
}
|
||
}
|
||
|
||
// Check RcsMatrixDataSource (List<List<double>>)
|
||
Assert.IsNotNull(actualMatrixDataSource);
|
||
Assert.AreEqual(6, actualMatrixDataSource.Count);
|
||
for (int i = 0; i < 6; i++)
|
||
{
|
||
Assert.IsNotNull(actualMatrixDataSource[i]);
|
||
Assert.AreEqual(4, actualMatrixDataSource[i].Count);
|
||
for (int j = 0; j < 4; j++)
|
||
{
|
||
Assert.AreEqual(expectedMatrix[i, j], actualMatrixDataSource[i][j], TEST_DELTA, $"RcsMatrixDataSource[{i}][{j}] 没有匹配预期。");
|
||
}
|
||
}
|
||
}
|
||
|
||
[TestMethod]
|
||
public void ParameterizedConstructor_WithNullMatrix_ThrowsArgumentNullException()
|
||
{
|
||
double[,]? nullMatrix = null;
|
||
|
||
Assert.ThrowsException<ArgumentNullException>(() => new RcsPattern(nullMatrix!));
|
||
}
|
||
|
||
[TestMethod]
|
||
public void ParameterizedConstructor_WithInvalidDimensions_ThrowsArgumentException()
|
||
{
|
||
double[,] wrongRowsMatrix = CreateTestMatrix(5, 4);
|
||
double[,] wrongColsMatrix = CreateTestMatrix(6, 3);
|
||
|
||
Assert.ThrowsException<ArgumentException>(() => new RcsPattern(wrongRowsMatrix), "构造函数应该在行数错误时抛出异常。");
|
||
Assert.ThrowsException<ArgumentException>(() => new RcsPattern(wrongColsMatrix), "构造函数应该在列数错误时抛出异常。");
|
||
}
|
||
|
||
[TestMethod]
|
||
public void RcsMatrixData_HandlesInvalidDataSource_ReturnsDefault()
|
||
{
|
||
var rcsPattern = new RcsPattern(); // 以有效的默认值开始
|
||
var defaultMatrix = CreateTestMatrix(6, 4, (r,c) => DEFAULT_RCS_DBSM_IN_PATTERN);
|
||
|
||
// 执行与断言 案例1:DataSource 为 null
|
||
rcsPattern.RcsMatrixDataSource = null!;
|
||
var rcsDataAfterNullSource = rcsPattern.RcsMatrixData;
|
||
CollectionAssert.AreEqual(defaultMatrix, rcsDataAfterNullSource, "RcsMatrixData 应该在 DataSource 为 null 时返回默认值。");
|
||
|
||
// 执行与断言 案例2:DataSource 的行数错误
|
||
rcsPattern.RcsMatrixDataSource = [[1, 2, 3, 4]]; // 只有 1 行
|
||
var rcsDataAfterWrongRowCount = rcsPattern.RcsMatrixData;
|
||
CollectionAssert.AreEqual(defaultMatrix, rcsDataAfterWrongRowCount, "RcsMatrixData 应该在 DataSource 中处理行数错误,返回默认值。");
|
||
|
||
// 执行与断言 案例3:DataSource 中的某行为 null
|
||
rcsPattern = new RcsPattern(); // 重置为有效状态
|
||
rcsPattern.RcsMatrixDataSource[2] = null!; // 将其中一行设置为 null
|
||
var rcsDataAfterNullRow = rcsPattern.RcsMatrixData;
|
||
// RcsPattern.ConvertSourceToGrid 会用默认值填充特定错误行,其他行保持不变。
|
||
// 因此,我们需要为此情况构造特定的预期矩阵。
|
||
var expectedMatrixWithOneDefaultRow = new RcsPattern().RcsMatrixData; // 以全默认值开始
|
||
// RcsPattern() 的原始测试矩阵就是默认矩阵。因此,此特定设置无需更改。
|
||
// 如果 RcsPattern() 的初始化方式不同,我们需要相应地调整 'expectedMatrixWithOneDefaultRow'。
|
||
CollectionAssert.AreEqual(expectedMatrixWithOneDefaultRow, rcsDataAfterNullRow, "RcsMatrixData 应该在 DataSource 中处理 null 行,通过默认该行。");
|
||
|
||
// 执行与断言 案例4:DataSource 中某行的列数错误
|
||
rcsPattern = new RcsPattern(); // 重置为有效状态
|
||
rcsPattern.RcsMatrixDataSource[3] = [1, 2, 3]; // 第3行只有3列
|
||
var rcsDataAfterWrongColCountInRow = rcsPattern.RcsMatrixData;
|
||
// 与案例3类似,RcsPattern.ConvertSourceToGrid 应将问题行置为默认值。
|
||
var expectedMatrixWithOneDefaultRowAgain = new RcsPattern().RcsMatrixData;
|
||
CollectionAssert.AreEqual(expectedMatrixWithOneDefaultRowAgain, rcsDataAfterWrongColCountInRow, "RcsMatrixData 应该在 DataSource 中处理某行的列数错误,通过默认该行。");
|
||
}
|
||
|
||
// GetRcsValueDbSm(double azimuthDeg, double elevationDeg) 的测试
|
||
// 基于角度的测试的辅助方法,使用可预测的矩阵
|
||
private RcsPattern CreateAngleTestPattern()
|
||
{
|
||
// 矩阵中 RcsMatrix[row, col] = (row + 1) * 100 + (col + 1) * 10 以便于识别
|
||
return new RcsPattern(CreateTestMatrix(6, 4, (r, c) => (r + 1) * 100 + (c + 1) * 10));
|
||
}
|
||
|
||
[DataTestMethod]
|
||
[DataRow(0.0, 0, DisplayName = "Top_Az0_Q0")]
|
||
[DataRow(45.0, 0, DisplayName = "Top_Az45_Q0")]
|
||
[DataRow(89.9, 0, DisplayName = "Top_Az89.9_Q0")]
|
||
[DataRow(90.0, 1, DisplayName = "Top_Az90_Q1")]
|
||
[DataRow(135.0, 1, DisplayName = "Top_Az135_Q1")]
|
||
[DataRow(179.9, 1, DisplayName = "Top_Az179.9_Q1")]
|
||
[DataRow(-0.1, 3, DisplayName = "Top_Az-0.1_Q3")]
|
||
[DataRow(-45.0, 3, DisplayName = "Top_Az-45_Q3")]
|
||
[DataRow(-89.9, 3, DisplayName = "Top_Az-89.9_Q3")]
|
||
[DataRow(-90.0, 2, DisplayName = "Top_Az-90_Q2")]
|
||
[DataRow(-135.0, 2, DisplayName = "Top_Az-135_Q2")]
|
||
[DataRow(-179.9, 2, DisplayName = "Top_Az-179.9_Q2")]
|
||
[DataRow(180.0, 2, DisplayName = "Top_Az180_Q2")]
|
||
[DataRow(-180.0, 2, DisplayName = "Top_Az-180_Q2")]
|
||
public void GetRcsAngleBased_TopAspect_ReturnsCorrectQuadrantValue(double azimuthDeg, int expectedQuadrantColumn)
|
||
{
|
||
var rcsPattern = CreateAngleTestPattern();
|
||
double elevationDeg = 75.0;
|
||
int expectedMajorAspectRow = 4;
|
||
double expectedValue = (expectedMajorAspectRow + 1) * 100 + (expectedQuadrantColumn + 1) * 10;
|
||
|
||
double actualValue = rcsPattern.GetRcsValueDbSm(azimuthDeg, elevationDeg);
|
||
|
||
Assert.AreEqual(expectedValue, actualValue, TEST_DELTA, $"失败 for Az: {azimuthDeg}, El: {elevationDeg}. 预期行 {expectedMajorAspectRow}, 列 {expectedQuadrantColumn}.");
|
||
}
|
||
|
||
[DataTestMethod]
|
||
// 与顶部视角类似的数据行,仅高程为-75
|
||
[DataRow(0.0, 0, DisplayName = "Bottom_Az0_Q0")]
|
||
[DataRow(89.9, 0, DisplayName = "Bottom_Az89.9_Q0")]
|
||
[DataRow(90.0, 1, DisplayName = "Bottom_Az90_Q1")]
|
||
[DataRow(179.9, 1, DisplayName = "Bottom_Az179.9_Q1")]
|
||
[DataRow(-0.1, 3, DisplayName = "Bottom_Az-0.1_Q3")]
|
||
[DataRow(-89.9, 3, DisplayName = "Bottom_Az-89.9_Q3")]
|
||
[DataRow(-90.0, 2, DisplayName = "Bottom_Az-90_Q2")]
|
||
[DataRow(-179.9, 2, DisplayName = "Bottom_Az-179.9_Q2")]
|
||
[DataRow(180.0, 2, DisplayName = "Bottom_Az180_Q2")]
|
||
[DataRow(-180.0, 2, DisplayName = "Bottom_Az-180_Q2")]
|
||
public void GetRcsAngleBased_BottomAspect_ReturnsCorrectQuadrantValue(double azimuthDeg, int expectedQuadrantColumn)
|
||
{
|
||
var rcsPattern = CreateAngleTestPattern();
|
||
double elevationDeg = -75.0; // 底部视角
|
||
int expectedMajorAspectRow = 5; // 底部
|
||
double expectedValue = (expectedMajorAspectRow + 1) * 100 + (expectedQuadrantColumn + 1) * 10;
|
||
|
||
double actualValue = rcsPattern.GetRcsValueDbSm(azimuthDeg, elevationDeg);
|
||
|
||
Assert.AreEqual(expectedValue, actualValue, TEST_DELTA, $"失败 for Az: {azimuthDeg}, El: {elevationDeg}. 预期行 {expectedMajorAspectRow}, 列 {expectedQuadrantColumn}.");
|
||
}
|
||
|
||
// 正面视角 (行 0)
|
||
[DataTestMethod]
|
||
[DataRow(0.0, 30.0, 0, DisplayName = "Front_Az0_El30_Q0_TopRight")]
|
||
[DataRow(44.9, 30.0, 0, DisplayName = "Front_Az44.9_El30_Q0_TopRight")]
|
||
[DataRow(0.0, -30.0, 3, DisplayName = "Front_Az0_El-30_Q3_BottomRight")]
|
||
[DataRow(44.9, -30.0, 3, DisplayName = "Front_Az44.9_El-30_Q3_BottomRight")]
|
||
[DataRow(-0.1, 30.0, 1, DisplayName = "Front_Az-0.1_El30_Q1_TopLeft")]
|
||
[DataRow(-44.9, 30.0, 1, DisplayName = "Front_Az-44.9_El30_Q1_TopLeft")]
|
||
[DataRow(-0.1, -30.0, 2, DisplayName = "Front_Az-0.1_El-30_Q2_BottomLeft")]
|
||
[DataRow(-44.9, -30.0, 2, DisplayName = "Front_Az-44.9_El-30_Q2_BottomLeft")]
|
||
public void GetRcsAngleBased_FrontAspect_ReturnsCorrectQuadrantValue(double azimuthDeg, double elevationDeg, int expectedQuadrantColumn)
|
||
{
|
||
var rcsPattern = CreateAngleTestPattern();
|
||
int expectedMajorAspectRow = 0;
|
||
double expectedValue = (expectedMajorAspectRow + 1) * 100 + (expectedQuadrantColumn + 1) * 10;
|
||
double actualValue = rcsPattern.GetRcsValueDbSm(azimuthDeg, elevationDeg);
|
||
Assert.AreEqual(expectedValue, actualValue, TEST_DELTA, $"正面视角 - 失败 for Az: {azimuthDeg}, El: {elevationDeg}.");
|
||
}
|
||
|
||
// 背面视角 (行 1) - 背面方位角为 135 到 -135 (或 135 到 225)
|
||
[DataTestMethod]
|
||
[DataRow(179.9, 30.0, 0, DisplayName = "Back_Az179.9_El30_Q0_TopRight")] // 方位角 179.9 (>0), 高程 > 0 -> 背面, Q0 (简化逻辑)
|
||
[DataRow(135.1, 30.0, 0, DisplayName = "Back_Az135.1_El30_Q0_TopRight")] // 方位角 135.1 (>0), 高程 > 0 -> 背面, Q0
|
||
[DataRow(179.9, -30.0, 3, DisplayName = "Back_Az179.9_El-30_Q3_BottomRight")]// 方位角 179.9 (>0), 高程 < 0 -> 背面, Q3
|
||
[DataRow(135.1, -30.0, 3, DisplayName = "Back_Az135.1_El-30_Q3_BottomRight")]// 方位角 135.1 (>0), 高程 < 0 -> 背面, Q3
|
||
[DataRow(-179.9, 30.0, 1, DisplayName = "Back_Az-179.9_El30_Q1_TopLeft")] // 方位角 -179.9 (<0), 高程 > 0 -> 背面, Q1
|
||
[DataRow(-135.1, 30.0, 1, DisplayName = "Back_Az-135.1_El30_Q1_TopLeft")] // 方位角 -135.1 (<0), 高程 > 0 -> 背面, Q1
|
||
[DataRow(-179.9, -30.0, 2, DisplayName = "Back_Az-179.9_El-30_Q2_BottomLeft")]// 方位角 -179.9 (<0), 高程 < 0 -> 背面, Q2
|
||
[DataRow(-135.1, -30.0, 2, DisplayName = "Back_Az-135.1_El-30_Q2_BottomLeft")]// 方位角 -135.1 (<0), 高程 < 0 -> 背面, Q2
|
||
[DataRow(180.0, 30.0, 1, DisplayName = "Back_Az180_El30_Q0_TopRight")] // 方位角 180.0, 高程 > 0 -> 背面, Q0 (简化逻辑)
|
||
[DataRow(-180.0, 30.0, 1, DisplayName = "Back_Az-180_El30_Q1_TopLeft")]// 方位角 -180.0, 高程 > 0 -> 背面, Q1 (简化逻辑)
|
||
public void GetRcsAngleBased_BackAspect_ReturnsCorrectQuadrantValue(double azimuthDeg, double elevationDeg, int expectedQuadrantColumn)
|
||
{
|
||
var rcsPattern = CreateAngleTestPattern();
|
||
int expectedMajorAspectRow = 1; // 背面
|
||
double expectedValue = (expectedMajorAspectRow + 1) * 100 + (expectedQuadrantColumn + 1) * 10;
|
||
double actualValue = rcsPattern.GetRcsValueDbSm(azimuthDeg, elevationDeg);
|
||
Assert.AreEqual(expectedValue, actualValue, TEST_DELTA, $"背面视角 - 失败 for Az: {azimuthDeg}, El: {elevationDeg}.");
|
||
}
|
||
|
||
// 右侧视角 (行 3) - 右侧方位角为 45 到 135
|
||
[DataTestMethod]
|
||
[DataRow(45.1, 30.0, 0, DisplayName = "Right_Az45.1_El30_Q0_TopRight")] // 方位角 45.1 (<90), 高程 > 0 -> 右侧, Q0
|
||
[DataRow(89.9, 30.0, 0, DisplayName = "Right_Az89.9_El30_Q0_TopRight")] // 方位角 89.9 (<90), 高程 > 0 -> 右侧, Q0
|
||
[DataRow(45.1, -30.0, 3, DisplayName = "Right_Az45.1_El-30_Q3_BottomRight")]// 方位角 45.1 (<90), 高程 < 0 -> 右侧, Q3
|
||
[DataRow(89.9, -30.0, 3, DisplayName = "Right_Az89.9_El-30_Q3_BottomRight")]// 方位角 89.9 (<90), 高程 < 0 -> 右侧, Q3
|
||
[DataRow(90.1, 30.0, 1, DisplayName = "Right_Az90.1_El30_Q1_TopLeft")] // 方位角 90.1 (>=90), 高程 > 0 -> 右侧, Q1
|
||
[DataRow(134.9, 30.0, 1, DisplayName = "Right_Az134.9_El30_Q1_TopLeft")] // 方位角 134.9 (>=90), 高程 > 0 -> 右侧, Q1
|
||
[DataRow(90.1, -30.0, 2, DisplayName = "Right_Az90.1_El-30_Q2_BottomLeft")] // 方位角 90.1 (>=90), 高程 < 0 -> 右侧, Q2
|
||
[DataRow(134.9, -30.0, 2, DisplayName = "Right_Az134.9_El-30_Q2_BottomLeft")]// 方位角 134.9 (>=90), 高程 < 0 -> 右侧, Q2
|
||
public void GetRcsAngleBased_RightAspect_ReturnsCorrectQuadrantValue(double azimuthDeg, double elevationDeg, int expectedQuadrantColumn)
|
||
{
|
||
var rcsPattern = CreateAngleTestPattern();
|
||
int expectedMajorAspectRow = 3; // 右侧
|
||
double expectedValue = (expectedMajorAspectRow + 1) * 100 + (expectedQuadrantColumn + 1) * 10;
|
||
double actualValue = rcsPattern.GetRcsValueDbSm(azimuthDeg, elevationDeg);
|
||
Assert.AreEqual(expectedValue, actualValue, TEST_DELTA, $"右侧视角 - 失败 for Az: {azimuthDeg}, El: {elevationDeg}.");
|
||
}
|
||
|
||
// 左侧视角 (行 2) - 左侧方位角为 -45 到 -135
|
||
[DataTestMethod]
|
||
[DataRow(-45.1, 30.0, 1, DisplayName = "Left_Az-45.1_El30_Q1_TopLeft")] // 方位角 -45.1 (不 < -90), 高程 > 0 -> 左侧, Q1
|
||
[DataRow(-89.9, 30.0, 1, DisplayName = "Left_Az-89.9_El30_Q1_TopLeft")] // 方位角 -89.9 (不 < -90), 高程 > 0 -> 左侧, Q1
|
||
[DataRow(-45.1, -30.0, 2, DisplayName = "Left_Az-45.1_El-30_Q2_BottomLeft")]// 方位角 -45.1 (不 < -90), 高程 < 0 -> 左侧, Q2
|
||
[DataRow(-89.9, -30.0, 2, DisplayName = "Left_Az-89.9_El-30_Q2_BottomLeft")]// 方位角 -89.9 (不 < -90), 高程 < 0 -> 左侧, Q2
|
||
[DataRow(-90.1, 30.0, 0, DisplayName = "Left_Az-90.1_El30_Q0_TopRight")] // 方位角 -90.1 (< -90), 高程 > 0 -> 左侧, Q0
|
||
[DataRow(-134.9, 30.0, 0, DisplayName = "Left_Az-134.9_El30_Q0_TopRight")] // 方位角 -134.9 (< -90), 高程 > 0 -> 左侧, Q0
|
||
[DataRow(-90.1, -30.0, 3, DisplayName = "Left_Az-90.1_El-30_Q3_BottomRight")]// 方位角 -90.1 (< -90), 高程 < 0 -> 左侧, Q3
|
||
[DataRow(-134.9, -30.0, 3, DisplayName = "Left_Az-134.9_El-30_Q3_BottomRight")]// 方位角 -134.9 (< -90), 高程 < 0 -> 左侧, Q3
|
||
public void GetRcsAngleBased_LeftAspect_ReturnsCorrectQuadrantValue(double azimuthDeg, double elevationDeg, int expectedQuadrantColumn)
|
||
{
|
||
var rcsPattern = CreateAngleTestPattern();
|
||
int expectedMajorAspectRow = 2; // 左侧
|
||
double expectedValue = (expectedMajorAspectRow + 1) * 100 + (expectedQuadrantColumn + 1) * 10;
|
||
double actualValue = rcsPattern.GetRcsValueDbSm(azimuthDeg, elevationDeg);
|
||
Assert.AreEqual(expectedValue, actualValue, TEST_DELTA, $"左侧视角 - 失败 for Az: {azimuthDeg}, El: {elevationDeg}.");
|
||
}
|
||
|
||
[TestMethod]
|
||
public void GetRcsAngleBased_InvalidAngles_ReturnsDefaultRcs()
|
||
{
|
||
var rcsPattern = CreateAngleTestPattern();
|
||
|
||
// 高程过高/过低 (应由方法限制,但最好测试逻辑的边界行为)
|
||
// 该方法基于高程 > 70 或 < -70 选择行的内部逻辑是稳健的。
|
||
// 此测试更关注具有有效高程的极端方位角。
|
||
Assert.AreEqual(rcsPattern.GetRcsValueDbSm(720, 30), rcsPattern.GetRcsValueDbSm(0, 30), TEST_DELTA, "方位角 720 应与 0 相同");
|
||
Assert.AreEqual(rcsPattern.GetRcsValueDbSm(-720, 30), rcsPattern.GetRcsValueDbSm(0, 30), TEST_DELTA, "方位角 -720 应与 0 相同");
|
||
|
||
// 测试高程限制
|
||
// 如果高程为 95,则限制为 90。行 4 (顶部)。方位角 0 -> 列 0。
|
||
double expectedTopQ0 = (4 + 1) * 100 + (0 + 1) * 10;
|
||
Assert.AreEqual(expectedTopQ0, rcsPattern.GetRcsValueDbSm(0, 95), TEST_DELTA, "Elevation 95 应被限制为 90, 顶部 Q0.");
|
||
|
||
// 如果高程为 -95,则限制为 -90。行 5 (底部)。方位角 0 -> 列 0。
|
||
double expectedBottomQ0 = (5 + 1) * 100 + (0 + 1) * 10;
|
||
Assert.AreEqual(expectedBottomQ0, rcsPattern.GetRcsValueDbSm(0, -95), TEST_DELTA, "Elevation -95 应被限制为 -90, 底部 Q0.");
|
||
|
||
// 测试是否有任何意外组合导致调试路径返回 DEFAULT_RCS_DBSM_IN_PATTERN
|
||
// 这需要在逻辑处理后找到 majorAspectRow 或 quadrantColumn 超出边界的情况。
|
||
// 鉴于当前逻辑,很难触发返回 DEFAULT_RCS_DBSM_IN_PATTERN 的最终 'else' 分支
|
||
// 因为方位角和高程归一化 + 选择逻辑似乎覆盖了所有输入。
|
||
// 但是,我们可以测试在没有 CreateAngleTestPattern 的情况下,底层矩阵可能为默认值的特定情况
|
||
var defaultPattern = new RcsPattern(); // 所有值均为 DEFAULT_RCS_DBSM_IN_PATTERN
|
||
// 如果 GetRcsValueDbSm 由于某种原因未能找到单元格并从其最终的 else 返回了 DEFAULT_RCS_DBSM_IN_PATTERN,
|
||
// 这将会通过。在没有更具体条件下,这不是对该路径的强力测试。
|
||
// 目前,我们假设现有的 DataRow 测试覆盖了有效的单元格选择。
|
||
// 对备用逻辑的更稳健测试是矩阵查找本身失败,这不是此方法测试的内容。
|
||
}
|
||
|
||
// GetRcsValueDbSm(Vector3D observerDirection, ...) 的测试
|
||
private readonly Vector3D TARGET_FORWARD = new(1, 0, 0);
|
||
private readonly Vector3D TARGET_UP = new(0, 1, 0);
|
||
private readonly Vector3D TARGET_RIGHT = new(0, 0, 1);
|
||
|
||
// 顶部视角 (行 4) - 观察者在远高于目标的位置
|
||
// 顶部局部坐标轴:localRight = targetRight (Z), localUp = -targetForward (-X)。
|
||
// Q0(Z>0, X<0), Q1(Z<0, X<0), Q2(Z<0, X>0), Q3(Z>0, X>0)。
|
||
[DataTestMethod]
|
||
[DataRow(-0.1, 10.0, 0.1, 0, DisplayName = "VectorTop_NearFwdSlightRight_Q0")] // X<0 (localUp), Z>0 (localRight) -> Q0 (观察者: -0.1, 10, 0.1)
|
||
[DataRow(-1.0, 10.0, 1.0, 0, DisplayName = "VectorTop_FwdLeft_Q0")] // X<0, Z>0 -> Q0
|
||
[DataRow(-1.0, 10.0, -1.0, 1, DisplayName = "VectorTop_FwdRight_Q1")]// X<0, Z<0 -> Q1
|
||
[DataRow(1.0, 10.0, -1.0, 2, DisplayName = "VectorTop_BackRight_Q2")] // X>0, Z<0 -> Q2
|
||
[DataRow(1.0, 10.0, 1.0, 3, DisplayName = "VectorTop_BackLeft_Q3")] // X>0, Z>0 -> Q3
|
||
public void GetRcsVectorBased_TopAspect_ReturnsCorrectQuadrantValue(double obsX, double obsY, double obsZ, int expectedQuadrantColumn)
|
||
{
|
||
var rcsPattern = CreateAngleTestPattern();
|
||
var observerDirection = new Vector3D(obsX, obsY, obsZ);
|
||
int expectedMajorAspectRow = 4;
|
||
double expectedValue = (expectedMajorAspectRow + 1) * 100 + (expectedQuadrantColumn + 1) * 10;
|
||
|
||
double actualValue = rcsPattern.GetRcsValueDbSm(observerDirection, TARGET_FORWARD, TARGET_UP, TARGET_RIGHT);
|
||
|
||
Assert.AreEqual(expectedValue, actualValue, TEST_DELTA, $"Vector Top Aspect - 失败 for Obs: {observerDirection}. 预期行 {expectedMajorAspectRow}, 列 {expectedQuadrantColumn}.");
|
||
}
|
||
|
||
// 底部视角 (行 5) - 观察者在远低于目标的位置
|
||
// 底部局部坐标轴:localRight = targetRight (Z), localUp = targetForward (X)。
|
||
// Q0(Z>0, X>0), Q1(Z<0, X>0), Q2(Z<0, X<0), Q3(Z>0, X<0)。
|
||
[DataTestMethod]
|
||
[DataRow(1.0, -10.0, 1.0, 0, DisplayName = "VectorBottom_FwdLeft_Q0")] // X>0 (localUp), Z>0 (localRight) -> Q0
|
||
[DataRow(1.0, -10.0, -1.0, 1, DisplayName = "VectorBottom_FwdRight_Q1")] // X>0, Z<0 -> Q1
|
||
[DataRow(-1.0, -10.0, -1.0, 2, DisplayName = "VectorBottom_BackRight_Q2")]// X<0, Z<0 -> Q2
|
||
[DataRow(-1.0, -10.0, 1.0, 3, DisplayName = "VectorBottom_BackLeft_Q3")] // X<0, Z>0 -> Q3
|
||
public void GetRcsVectorBased_BottomAspect_ReturnsCorrectQuadrantValue(double obsX, double obsY, double obsZ, int expectedQuadrantColumn)
|
||
{
|
||
var rcsPattern = CreateAngleTestPattern();
|
||
var observerDirection = new Vector3D(obsX, obsY, obsZ);
|
||
int expectedMajorAspectRow = 5;
|
||
double expectedValue = (expectedMajorAspectRow + 1) * 100 + (expectedQuadrantColumn + 1) * 10;
|
||
|
||
double actualValue = rcsPattern.GetRcsValueDbSm(observerDirection, TARGET_FORWARD, TARGET_UP, TARGET_RIGHT);
|
||
|
||
Assert.AreEqual(expectedValue, actualValue, TEST_DELTA, $"Vector Bottom Aspect - 失败 for Obs: {observerDirection}. 预期行 {expectedMajorAspectRow}, 列 {expectedQuadrantColumn}.");
|
||
}
|
||
|
||
// 正面视角 (行 0) - 观察者在前方 (如果 TARGET_FORWARD 是 (1,0,0),则观察者在目标前方的正 X 方向)
|
||
// 全局方位角接近 0。observerDirection 应在 TARGET_FORWARD 方向上具有较大的正分量。
|
||
// 正面局部坐标轴:localRight = targetRight (Z), localUp = targetUp (Y)。
|
||
// Q0(Z>=0, Y>=0), Q1(Z<0, Y>=0), Q2(Z<0, Y<0), Q3(Z>=0, Y<0)。
|
||
[DataTestMethod]
|
||
[DataRow(10.0, 1.0, 1.0, 0, DisplayName = "VectorFront_UpRightQuadrant_Q0")]
|
||
[DataRow(10.0, 1.0, -1.0, 1, DisplayName = "VectorFront_UpLeftQuadrant_Q1")]
|
||
[DataRow(10.0, -1.0, -1.0, 2, DisplayName = "VectorFront_DownLeftQuadrant_Q2")]
|
||
[DataRow(10.0, -1.0, 1.0, 3, DisplayName = "VectorFront_DownRightQuadrant_Q3")]
|
||
// 测试点积为零的边界情况
|
||
[DataRow(10.0, 0.0, 0.001, 0, DisplayName = "VectorFront_Y0_Zpos_Q0")] // Y=0, Z>0. dot(obs,Y)=0. isLocallyTopQuadrant=true. isLocallyRightQuadrant=true. -> Q0
|
||
[DataRow(10.0, 0.0, -0.001, 1, DisplayName = "VectorFront_Y0_Zneg_Q1")]// Y=0, Z<0. isLocallyTopQuadrant=true. isLocallyRightQuadrant=false. -> Q1
|
||
[DataRow(10.0, 0.001, 0.0, 0, DisplayName = "VectorFront_Ypos_Z0_Q0")] // Y>0, Z=0. isLocallyTopQuadrant=true. isLocallyRightQuadrant=true. -> Q0
|
||
[DataRow(10.0, -0.001, 0.0, 3, DisplayName = "VectorFront_Yneg_Z0_Q3")]// Y<0, Z=0. isLocallyTopQuadrant=false. isLocallyRightQuadrant=true. -> Q3
|
||
public void GetRcsVectorBased_FrontAspect_ReturnsCorrectQuadrantValue(double obsX, double obsY, double obsZ, int expectedQuadrantColumn)
|
||
{
|
||
var rcsPattern = CreateAngleTestPattern();
|
||
var observerDirection = new Vector3D(obsX, obsY, obsZ);
|
||
int expectedMajorAspectRow = 0;
|
||
double expectedValue = (expectedMajorAspectRow + 1) * 100 + (expectedQuadrantColumn + 1) * 10;
|
||
double actualValue = rcsPattern.GetRcsValueDbSm(observerDirection, TARGET_FORWARD, TARGET_UP, TARGET_RIGHT);
|
||
Assert.AreEqual(expectedValue, actualValue, TEST_DELTA, $"Vector Front Aspect - 失败 for Obs: {observerDirection}.");
|
||
}
|
||
|
||
// 背面视角 (行 1) - 观察者在后方 (相对于目标前方的负X方向)
|
||
// 背面局部坐标轴:localRight = -targetRight (-Z), localUp = targetUp (Y)。
|
||
// Q0(Z<=0, Y>=0), Q1(Z>0, Y>=0), Q2(Z>0, Y<0), Q3(Z<=0, Y<0)。
|
||
[DataTestMethod]
|
||
[DataRow(-10.0, 1.0, -1.0, 0, DisplayName = "VectorBack_UpLeftFacingTarget_Q0")]
|
||
[DataRow(-10.0, 1.0, 1.0, 1, DisplayName = "VectorBack_UpRightFacingTarget_Q1")]
|
||
[DataRow(-10.0, -1.0, 1.0, 2, DisplayName = "VectorBack_DownRightFacingTarget_Q2")]
|
||
[DataRow(-10.0, -1.0, -1.0, 3, DisplayName = "VectorBack_DownLeftFacingTarget_Q3")]
|
||
public void GetRcsVectorBased_BackAspect_ReturnsCorrectQuadrantValue(double obsX, double obsY, double obsZ, int expectedQuadrantColumn)
|
||
{
|
||
var rcsPattern = CreateAngleTestPattern();
|
||
var observerDirection = new Vector3D(obsX, obsY, obsZ);
|
||
int expectedMajorAspectRow = 1;
|
||
double expectedValue = (expectedMajorAspectRow + 1) * 100 + (expectedQuadrantColumn + 1) * 10;
|
||
double actualValue = rcsPattern.GetRcsValueDbSm(observerDirection, TARGET_FORWARD, TARGET_UP, TARGET_RIGHT);
|
||
Assert.AreEqual(expectedValue, actualValue, TEST_DELTA, $"Vector Back Aspect - 失败 for Obs: {observerDirection}.");
|
||
}
|
||
|
||
// 右侧视角 (行 3) - 观察者在右侧 (如果 TARGET_RIGHT 是 (0,0,1),则观察者在目标右侧的正Z方向)
|
||
// 右侧局部坐标轴:localRight = -targetForward (-X), localUp = targetUp (Y)。
|
||
// Q0(X<=0, Y>=0), Q1(X>0, Y>=0), Q2(X>0, Y<0), Q3(X<=0, Y<0)。
|
||
[DataTestMethod]
|
||
[DataRow(-1.0, 1.0, 10.0, 0, DisplayName = "VectorRight_UpFrontOfTarget_Q0")]
|
||
[DataRow(1.0, 1.0, 10.0, 1, DisplayName = "VectorRight_UpBackOfTarget_Q1")]
|
||
[DataRow(1.0, -1.0, 10.0, 2, DisplayName = "VectorRight_DownBackOfTarget_Q2")]
|
||
[DataRow(-1.0, -1.0, 10.0, 3, DisplayName = "VectorRight_DownFrontOfTarget_Q3")]
|
||
public void GetRcsVectorBased_RightAspect_ReturnsCorrectQuadrantValue(double obsX, double obsY, double obsZ, int expectedQuadrantColumn)
|
||
{
|
||
var rcsPattern = CreateAngleTestPattern();
|
||
var observerDirection = new Vector3D(obsX, obsY, obsZ);
|
||
int expectedMajorAspectRow = 3;
|
||
double expectedValue = (expectedMajorAspectRow + 1) * 100 + (expectedQuadrantColumn + 1) * 10;
|
||
double actualValue = rcsPattern.GetRcsValueDbSm(observerDirection, TARGET_FORWARD, TARGET_UP, TARGET_RIGHT);
|
||
Assert.AreEqual(expectedValue, actualValue, TEST_DELTA, $"Vector Right Aspect - 失败 for Obs: {observerDirection}.");
|
||
}
|
||
|
||
// 左侧视角 (行 2) - 观察者在左侧 (相对于目标右侧的负Z方向)
|
||
// 左侧局部坐标轴:localRight = targetForward (X), localUp = targetUp (Y)。
|
||
// Q0(X>=0, Y>=0), Q1(X<0, Y>=0), Q2(X<0, Y<0), Q3(X>=0, Y<0)。
|
||
[DataTestMethod]
|
||
[DataRow(1.0, 1.0, -10.0, 0, DisplayName = "VectorLeft_UpBackOfTarget_Q0")]
|
||
[DataRow(-1.0, 1.0, -10.0, 1, DisplayName = "VectorLeft_UpFrontOfTarget_Q1")]
|
||
[DataRow(-1.0, -1.0, -10.0, 2, DisplayName = "VectorLeft_DownFrontOfTarget_Q2")]
|
||
[DataRow(1.0, -1.0, -10.0, 3, DisplayName = "VectorLeft_DownBackOfTarget_Q3")]
|
||
public void GetRcsVectorBased_LeftAspect_ReturnsCorrectQuadrantValue(double obsX, double obsY, double obsZ, int expectedQuadrantColumn)
|
||
{
|
||
var rcsPattern = CreateAngleTestPattern();
|
||
var observerDirection = new Vector3D(obsX, obsY, obsZ);
|
||
int expectedMajorAspectRow = 2;
|
||
double expectedValue = (expectedMajorAspectRow + 1) * 100 + (expectedQuadrantColumn + 1) * 10;
|
||
double actualValue = rcsPattern.GetRcsValueDbSm(observerDirection, TARGET_FORWARD, TARGET_UP, TARGET_RIGHT);
|
||
Assert.AreEqual(expectedValue, actualValue, TEST_DELTA, $"Vector Left Aspect - 失败 for Obs: {observerDirection}.");
|
||
}
|
||
|
||
[TestMethod]
|
||
public void GetRcsVectorBased_SpecialVectors_ReturnsExpected()
|
||
{
|
||
var rcsPattern = CreateAngleTestPattern();
|
||
|
||
// 观察者直接沿坐标轴 (应选择一个一致的象限)
|
||
// 正前方 (X轴): 应为正面 (行 0), Q0。
|
||
double expectedFrontQ0 = (0 + 1) * 100 + (0 + 1) * 10;
|
||
Assert.AreEqual(expectedFrontQ0, rcsPattern.GetRcsValueDbSm(new Vector3D(1,0,0), TARGET_FORWARD, TARGET_UP, TARGET_RIGHT), TEST_DELTA, "Directly Forward vector.");
|
||
|
||
// 正上方 (Y轴): 应为顶部 (行 4), Q0。
|
||
// 注意: 对于顶部视图, localUp = -forwardNorm, localRight = rightNorm。观察者 (0,1,0) 得到 Q0。
|
||
double expectedTopQ0 = (4 + 1) * 100 + (0 + 1) * 10;
|
||
Assert.AreEqual(expectedTopQ0, rcsPattern.GetRcsValueDbSm(new Vector3D(0,1,0), TARGET_FORWARD, TARGET_UP, TARGET_RIGHT), TEST_DELTA, "Directly Up vector.");
|
||
|
||
// 零观察者向量: 归一化为 (0,0,0), 结果为正面 (行 0), Q0。
|
||
Assert.AreEqual(expectedFrontQ0, rcsPattern.GetRcsValueDbSm(Vector3D.Zero, TARGET_FORWARD, TARGET_UP, TARGET_RIGHT), TEST_DELTA, "Zero observer vector.");
|
||
|
||
// 观察者直接向下 (0,-1,0): 应为底部 (行 5), Q0。
|
||
// 对于底部视图, localUp = forwardNorm, localRight = rightNorm。
|
||
double expectedBottomQ0 = (5+1)*100 + (0+1)*10;
|
||
Assert.AreEqual(expectedBottomQ0, rcsPattern.GetRcsValueDbSm(new Vector3D(0,-1,0), TARGET_FORWARD, TARGET_UP, TARGET_RIGHT), TEST_DELTA, "Directly Down vector.");
|
||
}
|
||
|
||
[TestMethod]
|
||
public void GetAverageRcsDbSm_ReturnsCorrectAverage()
|
||
{
|
||
var testMatrix = CreateTestMatrix(6, 4, (r, c) => 10.0);
|
||
var rcsPattern = new RcsPattern(testMatrix);
|
||
double expectedAverage = 10.0;
|
||
double actualAverage = rcsPattern.GetAverageRcsDbSm();
|
||
Assert.AreEqual(expectedAverage, actualAverage, TEST_DELTA, "平均值计算不正确.");
|
||
|
||
var variedMatrix = CreateTestMatrix();
|
||
rcsPattern = new RcsPattern(variedMatrix);
|
||
expectedAverage = 660.0 / 24.0;
|
||
actualAverage = rcsPattern.GetAverageRcsDbSm();
|
||
Assert.AreEqual(expectedAverage, actualAverage, TEST_DELTA, "平均值计算不正确.");
|
||
}
|
||
|
||
[TestMethod]
|
||
public void GetAverageRcsDbSm_WhenDataSourceIsNull_ReturnsDefault()
|
||
{
|
||
var rcsPattern = new RcsPattern
|
||
{
|
||
RcsMatrixDataSource = null!
|
||
};
|
||
double actualAverage = rcsPattern.GetAverageRcsDbSm();
|
||
// 如果 RcsMatrixDataSource 为 null,RcsMatrixData的getter将返回一个用默认值填充的网格,因此平均值为默认值。
|
||
Assert.AreEqual(DEFAULT_RCS_DBSM_IN_PATTERN, actualAverage, TEST_DELTA, "当DataSource为null, 平均值应为默认值.");
|
||
}
|
||
}
|
||
} |