绕行函数日志回调修改 回调进度日志添加 回调“取消函数执行”添加 飞机列表映射

This commit is contained in:
szdot 2024-01-08 14:31:01 +08:00
parent 9999891cde
commit 84a4baf1f2
11 changed files with 250 additions and 102 deletions

View File

@ -400,6 +400,10 @@ namespace FlightRouteV2
//坐标操作与验证
public static class FlyVecFun
{
/// <summary>
/// 随机种子
/// </summary>
public static int RandomSeed { get; set; } = 1;
/// <summary>
/// 航线 线间距 平方值
/// </summary>
@ -407,7 +411,11 @@ namespace FlightRouteV2
/// <summary>
/// 飞行过程中间距 平方值
/// </summary>
public static double SpaceBetweenSquare { get; set; } = 90000;
public static double SpaceBetweenSquare { get; set; } = 62500;
/// <summary>
/// 算绕行时 中间取点 true在正中间取点即 一个圆盘 false在一个圆柱体内取点
/// </summary>
public static bool singleCircle = true;
/// <summary>
/// 输出日志回调函数
/// </summary>
@ -507,7 +515,7 @@ namespace FlightRouteV2
}
// 生成一个随机数,用于从最小值下标列表中随机选择一个下标
Random random = new Random();
Random random = new Random(RandomSeed);
return minIndices[random.Next(minIndices.Count)];
}
/// <summary>
@ -1444,7 +1452,7 @@ namespace FlightRouteV2
/// <param name="StrPrint">日志输出 回调函数</param>
/// <param name="layHight">错层层高</param>
/// <returns>返回一个二维向量坐标集合 middle[0]是第一个中间航点 middle[1]是第二个中间航点 返回空数组则代表两个图形不在一个平面上或者不够4个点</returns>
public static List<List<Vector3>> CollisionLayer(Vector3[] aVecs, Vector3[] bVecs,string aName,string bName ,SomeCalculateWay StrPrint, double layHight = 220)
public static List<List<Vector3>> CollisionLayer(Vector3[] aVecs, Vector3[] bVecs,string aName,string bName ,SomeCalculateWay StrPrint, double layHight = 185)
{
long t = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
StrPrint("-------错层,开始-------");
@ -1565,10 +1573,13 @@ namespace FlightRouteV2
/// </summary>
/// <param name="aVecs">起始坐标集合</param>
/// <param name="bVecs">终点做标集合</param>
/// <param name="strPrint">日志输出 回调函数</param>
/// <param name="StrPrint">日志输出 回调函数</param>
/// <param name="GetVal">日志输出 回调函数</param>
/// <param name="isPass">out参数 返回true不碰撞程序直接返回 false有碰撞程序向下执行</param>
/// <returns>返回一个二维数组 返回值长度0没有检测到碰撞或绕行失败 长度1为一个中间航点 长度为3为三个中间航点顺序(前中后)</returns>
public static List<List<Vector3>> ABypassB(Vector3[] aVecs, Vector3[] bVecs, SomeCalculateWay StrPrint, Schedule GetVal)
public static List<List<Vector3>> ABypassB(Vector3[] aVecs, Vector3[] bVecs,SomeCalculateWay StrPrint, Schedule GetVal, CancellationToken cancellationToken, out bool isPass, List<int> mappingId = null)
{
isPass = false;
long t = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
StrPrint("-------3D绕行开始-------");
List<List<Vector3>> re = new List<List<Vector3>>();
@ -1578,10 +1589,22 @@ namespace FlightRouteV2
{
StrPrint("没有检测到碰撞,故不用添加中间航点");
StrPrint($"-------3D绕行结束-------");
isPass = true;
return re;//直接返回
}
///飞机总数
int planeCou = aVecs.Length;
///判断有没有给 映射的ID 没有就按顺序设置ID序号
if (mappingId == null)
{
mappingId = new List<int>();
for (int i = 1; i <= planeCou; i++)
{
mappingId.Add(i);
}
}
///碰撞数
int collisionCou;
///第一次绕行 中间1航点
List<int> collisionGroup = TwoArrToArr(planesCollision); //整合数组
List<Vector3> middleVecs = new List<Vector3>(); //中心航点坐标组
@ -1589,11 +1612,21 @@ namespace FlightRouteV2
{
middleVecs.Add(SetMiddleVec(aVecs[i], bVecs[i])); //添加默认中间航点
}
for (int c = 0; c < 2; c++)
collisionCou = collisionGroup.Count;
while (true)
{
if (cancellationToken.IsCancellationRequested)//外部法取消指令
{
StrPrint("-------3D绕行操作被取消-------");
return re; // 退出函数
}
int progress = 0;//进度
foreach (int i in collisionGroup)//开始绕碰撞组
{
List<Vector3> grv = GetRingVec(aVecs[i], bVecs[i], 0.5, 40, 4);//中间可绕行航点列表
progress++;
GetVal(progress/collisionGroup.Count*100);
List<Vector3> grv = GetRingVec(aVecs[i], bVecs[i], 0.5, 5, 4, 1500);//中间可绕行航点列表
StrPrint($"进度:{progress}/{collisionGroup.Count},本次绕行{grv.Count}次");
foreach (Vector3 v in grv)
{
middleVecs[i] = v;
@ -1605,6 +1638,13 @@ namespace FlightRouteV2
}
planesCollision = AirImitation(aVecs, middleVecs).Concat(AirImitation(middleVecs, bVecs)).ToList(); //获取碰撞组
collisionGroup = TwoArrToArr(planesCollision); //整合数组
//如果绕行成功 或者 绕行结果和上次一样没有变化甚碰撞变多 则都退出循环
if (collisionGroup.Count == 0 || collisionCou <= collisionGroup.Count)
{
collisionCou = collisionGroup.Count;
break;
}
collisionCou = collisionGroup.Count;
}
//没有碰撞 返回一个中间航点 并返回
if (collisionGroup.Count == 0)
@ -1618,8 +1658,9 @@ namespace FlightRouteV2
}
else
{
StrPrint($"{string.Join(" ", collisionGroup)}号,有碰撞,共{collisionGroup.Count}架!");
StrPrint("第一次绕行未成功,准备开始第二次绕行!");
string mappingOutput = string.Join(", ", collisionGroup.Select(index => $"{mappingId[index]}号")); // 构建映射关系字符串
StrPrint($"共{collisionGroup.Count}架有碰撞:{mappingOutput}");
StrPrint("第一次绕行未成功!");
}
///第二次绕行 两头 两航点
@ -1633,18 +1674,25 @@ namespace FlightRouteV2
secondMiddleVecsOne.Add(SetMiddleVec(aVecs[i], bVecs[i], 0.1)); //添加中间航点1
secondMiddleVecsTwo.Add(SetMiddleVec(aVecs[i], bVecs[i], 0.9)); //添加中间航点2
}
for (int c = 0; c < 2; c++)
collisionCou = collisionGroup.Count;
while (true)
{
if (cancellationToken.IsCancellationRequested)//外部法取消指令
{
StrPrint("-------3D绕行操作被取消-------");
return re; // 退出函数
}
int progress = 0;//进度
foreach (int i in collisionGroup)//开始绕碰撞组
{
progress++;
GetVal(progress / collisionGroup.Count * 100);
//StrPrint($"迭代{c}次{i}号绕行");
List<Vector3> sgrv1 = GetRingVec(aVecs[i], bVecs[i], 0.1, 40, 8);//中间可绕行航点列表
List<Vector3> sgrv2 = GetRingVec(aVecs[i], bVecs[i], 0.9, 40, 8);//中间可绕行航点列表
//if (sgrv1.Count > 250) sgrv1.RemoveRange(250, sgrv1.Count - 250);
//if (sgrv2.Count > 250) sgrv2.RemoveRange(250, sgrv2.Count - 250);
StrPrint($"进度:{progress}/{collisionGroup.Count},本次绕行{Math.Pow(sgrv2.Count,2)}次");
List<Vector3> sgrv1 = GetRingVec(aVecs[i], bVecs[i], 0, 30, 10,600);//中间可绕行航点列表
sgrv1.Insert(0, secondMiddleVecsOne[i]);
List<Vector3> sgrv2 = GetRingVec(aVecs[i], bVecs[i], 1, 30, 10,600);//中间可绕行航点列表
sgrv2.Insert(0, secondMiddleVecsTwo[i]);
StrPrint($"进度:{progress}/{collisionGroup.Count},本次绕行{sgrv1.Count * sgrv2.Count}次");
foreach (Vector3 v1 in sgrv1)
{
secondMiddleVecsOne[i] = v1;
@ -1667,6 +1715,13 @@ namespace FlightRouteV2
planesCollision = AirImitation(aVecs, secondMiddleVecsOne).Concat(AirImitation(secondMiddleVecsOne, secondMiddleVecsTwo)).ToList(); //获取碰撞组
planesCollision = planesCollision.Concat(AirImitation(secondMiddleVecsTwo, bVecs)).ToList();
collisionGroup = TwoArrToArr(planesCollision); //整合数组
//如果绕行成功 或者 绕行结果和上次一样没有变化甚碰撞变多 则都退出循环
if (collisionGroup.Count == 0 || collisionCou <= collisionGroup.Count)
{
collisionCou = collisionGroup.Count;
break;
}
collisionCou = collisionGroup.Count;
}
//没有碰撞 返回两个中间航点 并返回
if (collisionGroup.Count == 0)
@ -1681,31 +1736,37 @@ namespace FlightRouteV2
}
else
{
StrPrint($"{string.Join(" ", collisionGroup)}号,有碰撞,共{collisionGroup.Count}架!");
StrPrint("第二次绕行未通过,准备开始第三次绕行!");
string mappingOutput = string.Join(", ", collisionGroup.Select(index => $"{mappingId[index]}号")); // 构建映射关系字符串
StrPrint($"共{collisionGroup.Count}架有碰撞:{mappingOutput}");
StrPrint("第二次绕行未成功!");
}
///第三次绕行 两头 两航点 中间一行点 沿用第二次绕行
///第三次绕行 两头 两航点 中间一行点(实际添加两航点 但是0.6位置航点暂不启用留给第四次绕行) 沿用第二次绕行
isPassMark = false;
List<Vector3> thirdMiddleVecs = new List<Vector3>(); //中心航点坐标组
List<Vector3> thirdMiddleVecs = new List<Vector3>(); //中心航点坐标组1
for (int i = 0; i < planeCou; i++)
{
thirdMiddleVecs.Add(SetMiddleVec(secondMiddleVecsOne[i], secondMiddleVecsTwo[i], 0.5)); //添加中间航点(保持二次绕行的两端航点 在两端航点中间添加)
}
for (int c = 0; c < 2; c++)
while (true)
{
if (cancellationToken.IsCancellationRequested)//外部法取消指令
{
StrPrint("-------3D绕行操作被取消-------");
return re; // 退出函数
}
int progress = 0;//进度
foreach (int i in collisionGroup)//开始绕碰撞组
{
GetVal(progress / collisionGroup.Count * 100);
progress++;
//StrPrint($"迭代{c}次{i}号绕行");
List<Vector3> sgrv1 = GetRingVec(aVecs[i], bVecs[i], 0.1, 220, 8);//中间可绕行航点列表
List<Vector3> sgrv2 = GetRingVec(aVecs[i], bVecs[i], 0.9, 220, 8);//中间可绕行航点列表
List<Vector3> grv = GetRingVec(secondMiddleVecsOne[i], secondMiddleVecsTwo[i], 0.5, 220, 4);//中间可绕行航点列表
//if (sgrv1.Count > 300) sgrv1.RemoveRange(300, sgrv1.Count - 300);
//if (sgrv2.Count > 300) sgrv2.RemoveRange(300, sgrv2.Count - 300);
//if (grv.Count > 300) grv.RemoveRange(300, grv.Count - 300);
StrPrint($"进度:{progress}/{collisionGroup.Count},本次绕行{Math.Pow(sgrv2.Count, 3)}次");
List<Vector3> sgrv1 = GetRingVec(aVecs[i], bVecs[i], 0, 100, 10, 600);//中间可绕行航点列表
sgrv1.Insert(0, secondMiddleVecsOne[i]);
List<Vector3> sgrv2 = GetRingVec(aVecs[i], bVecs[i], 1, 100, 10, 600);//中间可绕行航点列表
sgrv2.Insert(0, secondMiddleVecsTwo[i]);
List<Vector3> grv = GetRingVec(secondMiddleVecsOne[i], secondMiddleVecsTwo[i], 0.5, 80, 4, 1500);//中间可绕行航点列表
StrPrint($"进度:{progress}/{collisionGroup.Count},本次绕行{sgrv1.Count * sgrv2.Count * grv.Count}次");
foreach (Vector3 vm in grv)
{
thirdMiddleVecs[i] = vm;
@ -1737,6 +1798,13 @@ namespace FlightRouteV2
planesCollision = planesCollision.Concat(AirImitation(thirdMiddleVecs, secondMiddleVecsTwo)).ToList();
planesCollision = planesCollision.Concat(AirImitation(secondMiddleVecsTwo, bVecs)).ToList();
collisionGroup = TwoArrToArr(planesCollision); //整合数组
//如果绕行成功 或者 绕行结果和上次一样没有变化甚碰撞变多 则都退出循环
if (collisionGroup.Count == 0 || collisionCou <= collisionGroup.Count)
{
collisionCou = collisionGroup.Count;
break;
}
collisionCou = collisionGroup.Count;
}
//没有碰撞 返回三个中间航点 并返回
if (collisionGroup.Count == 0)
@ -1752,8 +1820,9 @@ namespace FlightRouteV2
}
else
{
StrPrint($"{string.Join(" ", collisionGroup)}号,有碰撞,共{collisionGroup.Count}架!");
StrPrint("第三次绕行未成功,准备开始第四次绕行!");
string mappingOutput = string.Join(", ", collisionGroup.Select(index => $"{mappingId[index]}号")); // 构建映射关系字符串
StrPrint($"共{collisionGroup.Count}架有碰撞:{mappingOutput}");
StrPrint("第三次绕行未成功!");
}
///end
@ -1804,14 +1873,14 @@ namespace FlightRouteV2
Vector3 k_hat = (bVec - aVec).NormalizEd();
/// 计算右向量,使用 Vector3.UnitY 作为上向量 i帽
//Vector3 i_hat = CrossPro(Vector3.UnitY, k_hat).NormalizEd(); //固定方向i帽
Random random = new Random();// 生成一个随机的单位向量
Random random = new Random(RandomSeed);// 生成一个随机的单位向量
Vector3 randomVector = new Vector3((double)random.NextDouble(), (double)random.NextDouble(), (double)random.NextDouble());
Vector3 i_hat = CrossPro(k_hat, randomVector).NormalizEd();// 随机方向i帽
/// 计算上向量 j帽
Vector3 j_hat = CrossPro(k_hat, i_hat);
///计算 对应的偏移比例
double length = (bVec - aVec).GetMag();
double offShift = middleProportion;//偏移比例
double offShift = middleProportion; //偏移比例
if (direction == "retrun")
{
if (offCount % 2 == 1) //奇数
@ -1856,13 +1925,20 @@ namespace FlightRouteV2
/// <param name="bVec">目标点</param>
/// <param name="middleProportion">中间航点位置比例</param>
/// <param name="transfer">绕行航点密度(值越小密度越大) ps:传递圈函数的弦长 向量矩阵函数的层高</param>
/// <param name="paunch">绕行航点范围(值越小范围越大) ps:决定层的厚度 和 圈的直径 为 paunch/航线长度</param>
/// <param name="paunch">绕行航点范围(值越小范围越大 如:参数给4 圆盘的半径是a到b距离的1/4) ps:决定层的厚度 和 圈的直径 为 paunch/航线长度</param>
/// <param name="maxPaunchRadius">设定圆盘半径 的最大值 单位是厘米</param>
/// <param name="direction">层排布方向 "retrun"前后堆叠 "forward"向前排列(如:起点向目标点方向) "backward"向后排列</param>
/// <returns>绕行航点列表</returns>
private static List<Vector3> GetRingVec(Vector3 aVec, Vector3 bVec, double middleProportion, double transfer, double paunch,bool singleCircle =true, string direction = "retrun")
public static List<Vector3> GetRingVec(Vector3 aVec, Vector3 bVec, double middleProportion, double transfer, double paunch,double maxPaunchRadius, string direction = "retrun")
{
List<Vector3> ringVec = new List<Vector3>(); //记录所有绕行中间航点坐标
/// 根据a到b的长度 算出中间绕行几圈
int ringCou = (int)Math.Ceiling(GageLength(aVec, bVec) / paunch / transfer); //算层数和圈数 ps:层的厚度 和 圈的直径 为 paunch/航线长度
double discRadius = GageLength(aVec, bVec) / paunch;//圆盘半径
if (discRadius > maxPaunchRadius)
{
discRadius = maxPaunchRadius;//设定圆盘不经不超过最大值
}
int ringCou = (int)Math.Ceiling(discRadius / transfer ); //算层数和圈数 ps:层的厚度 和 圈的直径 为 paunch/航线长度
if (ringCou < 2) ringCou = 2; //最少两圈 两层
/// 不是单圈的话 设置层数跟圈数相等
int layCou = ringCou;
@ -1898,19 +1974,21 @@ namespace FlightRouteV2
/// <returns>拉散图案的坐标组</returns>
public static Vector3[] NormalPull(Vector3[] aVecs, Vector3[] bVecs, SomeCalculateWay StrPrint)
{
int planeCou = aVecs.Length; //获取飞机总数
Vector3[] new_aVecs = aVecs.ToArray();
Vector3[] new_bVecs = bVecs.ToArray();
int planeCou = new_aVecs.Length; //获取飞机总数
///a图b图 中心
Vector3 aCenterPos = GetPosCenter(aVecs, false);
Vector3 bCenterPos = GetPosCenter(bVecs, false);
Vector3 aCenterPos = GetPosCenter(new_aVecs, false);
Vector3 bCenterPos = GetPosCenter(new_bVecs, false);
///判断bVec 矩阵的数量长宽
for (int i = 0; i < planeCou; i++)//把矩阵高度压平
{
bVecs[i] = new Vector3(bVecs[i].X, 0, bVecs[i].Z);
new_bVecs[i] = new Vector3(new_bVecs[i].X, 0, new_bVecs[i].Z);
}
int row = 1 ;
for (int i = 0; i < planeCou-2; i++)
{
if (!(IsVecsOnLine(bVecs[i], bVecs[i + 1], bVecs[i + 2])))
if (!(IsVecsOnLine(new_bVecs[i], new_bVecs[i + 1], new_bVecs[i + 2])))
{
row = i+2;//列
break;
@ -1918,17 +1996,17 @@ namespace FlightRouteV2
}
int ran = (int)Math.Ceiling((double)planeCou/(double)row);//行
///计算a图的法线标量
Vector3 side1 = aVecs[1] - aVecs[0];
Vector3 side2 = aVecs[2] - aVecs[0];
Vector3 side1 = new_aVecs[1] - new_aVecs[0];
Vector3 side2 = new_aVecs[2] - new_aVecs[0];
Vector3 normal = CrossPro(side1, side2);
Vector3 normalScalar = normal.NormalizEd();//法线标量
normalScalar.Y = 0;//高度上压平
///判断a图 法线朝向 和 矩阵“平行”方向 获取此方向层数 ps:用于a图的拉散
if (GageLength(normalScalar, bVecs[0]) < GageLength(normalScalar * -1, bVecs[0]))
if (GageLength(normalScalar, new_bVecs[0]) < GageLength(normalScalar * -1, new_bVecs[0]))
{
normalScalar *= -1;//法线选择方向为 靠近矩阵1号机的方向 ps:由于取的三个点位置随机 按照右手定则 法线方向也随机
}
if (Math.Abs(AngleBetween(bVecs[row] - bVecs[0], normalScalar) - 90) < Math.Abs(AngleBetween(bVecs[1] - bVecs[0], normalScalar) - 90))
if (Math.Abs(AngleBetween(new_bVecs[row] - new_bVecs[0], normalScalar) - 90) < Math.Abs(AngleBetween(new_bVecs[1] - new_bVecs[0], normalScalar) - 90))
{
/// 图案“如平行于0 21 41..” 平行于列
for (int k = 0; k < row; k++)
@ -1938,24 +2016,34 @@ namespace FlightRouteV2
int cou = i * row + k;
if (cou > planeCou) break;// 溢出跳出
///判断图在矩阵的左方 还是右方
if (GageLength(aCenterPos, bVecs[0]) > GageLength(aCenterPos, bVecs[row - 1]))
if (GageLength(aCenterPos, new_bVecs[0]) > GageLength(aCenterPos, new_bVecs[row - 1]))
{
aVecs[cou] -= normalScalar * (row - k) * 300;//左方
new_aVecs[cou] -= normalScalar * (row - k) * 300;//左方
}
else
{
aVecs[cou] += normalScalar * k * 300;//右方
new_aVecs[cou] += normalScalar * k * 300;//右方
}
}
}
///判断a图的中心点 是否在矩阵内部 在矩阵内部 做一个a b两组中心点对其 ps:相当于朝两边拉散
if (IsPointBetweenLines(bVecs[(int)Math.Ceiling(((double)row/5))-1], bVecs[(int)Math.Ceiling(((double)row / 5)) - 1+row], bVecs[row-((int)Math.Ceiling(((double)row / 5)) - 1)], bVecs[(row - ((int)Math.Ceiling(((double)row / 5)) - 1))+row], aCenterPos))
if (IsPointBetweenLines(new_bVecs[(int)Math.Ceiling(((double)row/5))-1], new_bVecs[(int)Math.Ceiling(((double)row / 5)) - 1+row], new_bVecs[row-((int)Math.Ceiling(((double)row / 5)) - 1)], new_bVecs[(row - ((int)Math.Ceiling(((double)row / 5)) - 1))+row], aCenterPos))
{
aCenterPos = GetPosCenter(aVecs, false);//重新算下中心点
Vector3 offPos = aCenterPos - bCenterPos;//偏移量
for (int i = 0; i < planeCou; i++)
if (GageLength(new_aVecs[0], aVecs[0]) > GageLength(new_aVecs[planeCou - 1], aVecs[planeCou - 1]))//判断最大偏移量 是第一排 还是最后一排
{
aVecs[i] -= offPos;
Vector3 offPos = (new_aVecs[0] - aVecs[0]) * 0.5;//偏移量 的一半
for (int i = 0; i < planeCou; i++)//所有飞机重新计算偏移量 ps:向两侧拉开
{
new_aVecs[i] -= offPos;
}
}
else
{
Vector3 offPos = (new_aVecs[planeCou - 1] - aVecs[planeCou - 1]) * 0.5;//偏移量 的一半
for (int i = 0; i < planeCou; i++)//所有飞机重新计算偏移量 ps:向两侧拉开
{
new_aVecs[i] -= offPos;
}
}
}
@ -1970,28 +2058,38 @@ namespace FlightRouteV2
int cou = k * row + i;
if (cou > planeCou) break;// 溢出跳出
///判断图在矩阵的上方 还是下方
if (GageLength(aCenterPos, bVecs[0]) > GageLength(aCenterPos, bVecs[row * (ran - 1)]))
if (GageLength(aCenterPos, new_bVecs[0]) > GageLength(aCenterPos, new_bVecs[row * (ran - 1)]))
{
aVecs[cou] -= normalScalar * (ran - k) * 300;//上方
new_aVecs[cou] -= normalScalar * (ran - k) * 300;//上方
}
else
{
aVecs[cou] += normalScalar * k * 300;//下方
new_aVecs[cou] += normalScalar * k * 300;//下方
}
}
}
///判断a图的中心点 是否在矩阵内部 在矩阵内部 做一个a b两组中心点对其 ps:相当于朝两边拉散
if (IsPointBetweenLines(bVecs[(int)Math.Ceiling((double)ran / 5) * row - row], bVecs[(int)Math.Ceiling((double)ran / 5) * row - 1], bVecs[(ran - (int)Math.Ceiling((double)ran / 5)) * row], bVecs[(ran - (int)Math.Ceiling((double)ran / 5)) * row + row - 1], aCenterPos))
if (IsPointBetweenLines(new_bVecs[(int)Math.Ceiling((double)ran / 5) * row - row], new_bVecs[(int)Math.Ceiling((double)ran / 5) * row - 1], new_bVecs[(ran - (int)Math.Ceiling((double)ran / 5)) * row], new_bVecs[(ran - (int)Math.Ceiling((double)ran / 5)) * row + row - 1], aCenterPos))
{
aCenterPos = GetPosCenter(aVecs, false);//重新算下中心点
Vector3 offPos = aCenterPos - bCenterPos;//偏移量
for (int i = 0; i < planeCou; i++)
if (GageLength(new_aVecs[0], aVecs[0]) > GageLength(new_aVecs[planeCou - 1], aVecs[planeCou - 1]))//判断最大偏移量 是第一排 还是最后一排
{
aVecs[i] -= offPos;
Vector3 offPos = (new_aVecs[0] - aVecs[0]) * 0.5;//偏移量 的一半
for (int i = 0; i < planeCou; i++)//所有飞机重新计算偏移量 ps:向两侧拉开
{
new_aVecs[i] -= offPos;
}
}
else
{
Vector3 offPos = (new_aVecs[planeCou - 1] - aVecs[planeCou - 1]) * 0.5;//偏移量 的一半
for (int i = 0; i < planeCou; i++)//所有飞机重新计算偏移量 ps:向两侧拉开
{
new_aVecs[i] -= offPos;
}
}
}
}
return aVecs;
return new_aVecs;
}
}
}

View File

@ -16,13 +16,15 @@
<Label Content="顶视图" FontSize="14" Background="#556b6b6b" Foreground="#FFDCDCDC" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="0" />
</Canvas>
</Grid>
<Grid Name="MainMenu" Width="220" Height="800" Margin="10,0,0,0" HorizontalAlignment="Left" VerticalAlignment="Top">
<Button Content="导入航点" HorizontalAlignment="Left" VerticalAlignment="Top" Width="220" Height="49" Margin="0,0,0,0" Click="ImportFcgm_Click"/>
<Button Content="导入映射图" HorizontalAlignment="Left" VerticalAlignment="Top" Width="220" Height="49" Margin="0,54,0,0" Click="ImportImg_Click"/>
<Button Content="保存航点" HorizontalAlignment="Left" VerticalAlignment="Top" Width="220" Height="49" Margin="0,108,0,0" Click="ExportFcgm_Click"/>
<Button Content="渲染" HorizontalAlignment="Left" VerticalAlignment="Top" Width="220" Height="49" Margin="0,162,0,0" Click="Render_Click"/>
<Button Content="3D绕行" HorizontalAlignment="Left" VerticalAlignment="Top" Width="220" Height="49" Margin="0,270,0,0" Click="ByPass_Click"/>
<TextBox Name="vLogBox" HorizontalAlignment="Center" VerticalAlignment="Top" Width="220" Height="284" Margin="0,333,0,0"/>
<Button Content="绕行取消" HorizontalAlignment="Left" VerticalAlignment="Top" Width="220" Height="49" Margin="0,324,0,0" Click="ByPassCancel_Click"/>
<TextBox Name="vLogBox" HorizontalAlignment="Center" VerticalAlignment="Top" Width="220" Height="284" Margin="0,378,0,0"/>
</Grid>
</WrapPanel>
</Window>

View File

@ -21,12 +21,16 @@ using ControlLibrary;
using WpfAnimatedGif;//播放GIF
using System.Security.Cryptography;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Windows.Media.Animation;
namespace FlyCube
{
public partial class MainWindow : Window
{
private TextBox LOG;
//绕行线程取消
CancellationTokenSource cts = new CancellationTokenSource();
/// <summary>
/// 入口函数
/// </summary>
@ -35,12 +39,20 @@ namespace FlyCube
InitializeComponent();
//创建一个 主画布对象
TopCanvas = new MainCanvas(this.LayerPlane);
Vector3 A = new Vector3(0,0,0);
Vector3 B = new Vector3(0, 0, 10);
Vector3 C = new Vector3(10, 0, 0);
Vector3 D = new Vector3(10, 0, 10);
Vector3 P = new Vector3(10, 0, 10);
//MessageBox.Show(FlyVecFun.IsPointBetweenLines(A, B, C, D, P).ToString());
Vector3 aVec = new Vector3(-6650, 1585.775, 3150);
Vector3 bVec = new Vector3(-3864.256, 126.145,0);
List<Vector3> vecs = FlyVecFun.GetRingVec(aVec,bVec,0.3,100,1,1200);
string txta = "";
for (int i = 0; i < vecs.Count; i++)
{
txta += i + " 0" + " " + vecs[i].X + " " + vecs[i].Y + " " + vecs[i].Z + "\r\n";
}
if (File.Exists("C:/Users/szdot/Desktop/a.txt"))
{
File.Delete("C:/Users/szdot/Desktop/a.txt");
}
SaveFile("C:/Users/szdot/Desktop/a.txt", txta);
}
/// <summary>
/// 3D绕行
@ -56,67 +68,103 @@ namespace FlyCube
List<Vector3[]> abVecs = FileBase.TxtToPos(FliePath, out string[] fightNames);//从txt文件里面读取航点 信息
Vector3[] aVecs = abVecs[0].ToArray();
Vector3[] bVecs = abVecs[1].ToArray();
//Vector3[] new_bVecs = FlyVecFun.ContactABOut(aVecs, bVecs, StrPrint);
Vector3[] new_bVecs = FlyVecFun.NormalPull(aVecs, bVecs, StrPrintAsync);
Vector3[] new_bVecs = FlyVecFun.ContactABOut(aVecs, bVecs, StrPrint);
//Vector3[] new_aVecs = FlyVecFun.NormalPull(aVecs, bVecs, StrPrintAsync);
//Task<List<List<Vector3>>> reTask = Task.Run(() => FlyVecFun.ABypassB(aVecs, bVecs, StrPrintAsync, GetVal));
//List<List<Vector3>> re = await reTask;
bool isPass;
Task<List<List<Vector3>>> reTask = Task.Run(() => FlyVecFun.ABypassB(aVecs, bVecs, StrPrintAsync, GetVal, cts.Token, out isPass));
List<List<Vector3>> re = await reTask;
//string txta = "";
//string txtb = "";
//string txtc = "";
string txta = "";
string txtb = "";
string txtc = "";
string txtd = "";
for (int i = 0; i < abVecs[0].Length; i++)
{
// if (re.Count > 0)
// {
// txta += i + " 0" + " " + re[0][i].X + " " + re[0][i].Y + " " + re[0][i].Z + "\r\n";
// }
// if (re.Count > 1)
// {
// txtb += i + " 0" + " " + re[1][i].X + " " + re[1][i].Y + " " + re[1][i].Z + "\r\n";
// }
// if (re.Count > 2)
// {
// txtc += i + " 0" + " " + re[2][i].X + " " + re[2][i].Y + " " + re[2][i].Z + "\r\n";
// }
if (re.Count > 0)
{
txta += i + " 0" + " " + re[0][i].X + " " + re[0][i].Y + " " + re[0][i].Z + "\r\n";
}
if (re.Count > 1)
{
txtb += i + " 0" + " " + re[1][i].X + " " + re[1][i].Y + " " + re[1][i].Z + "\r\n";
}
if (re.Count > 2)
{
txtc += i + " 0" + " " + re[2][i].X + " " + re[2][i].Y + " " + re[2][i].Z + "\r\n";
}
txtd += i + " 0" + " " + new_bVecs[i].X + " " + new_bVecs[i].Y + " " + new_bVecs[i].Z + "\r\n";
}
//if (re.Count > 0)
//{
// SaveFile("C:/Users/szdot/Desktop/a.txt", txta);
//}
//if (re.Count > 1)
//{
// SaveFile("C:/Users/szdot/Desktop/b.txt", txtb);
//}
//if (re.Count > 2)
//{
// SaveFile("C:/Users/szdot/Desktop/c.txt", txtc);
//}
if (re.Count > 0)
{
string path = "C:/Users/szdot/Desktop/a.txt";
if (File.Exists(path))
{
File.Delete(path);
}
SaveFile(path, txta);
}
if (re.Count > 1)
{
string path = "C:/Users/szdot/Desktop/b.txt";
if (File.Exists(path))
{
File.Delete(path);
}
SaveFile(path, txtb);
}
if (re.Count > 2)
{
string path = "C:/Users/szdot/Desktop/c.txt";
if (File.Exists(path))
{
File.Delete(path);
}
SaveFile(path, txtc);
}
SaveFile("C:/Users/szdot/Desktop/d.txt", txtd);
string pathd = "C:/Users/szdot/Desktop/d.txt";
if (File.Exists(pathd))
{
File.Delete(pathd);
}
SaveFile(pathd, txtd);
}
else
{
return;
}
}
//绕行取消
private void ByPassCancel_Click(object sender, RoutedEventArgs e)
{
cts.Cancel(); //取消掉 异步执行的 绕行函数
}
//异步回调函数 控制 取消绕行函数执行
private bool IsBreak(bool val)
{
return val;
}
// 异步回调函数 输出日志
private async void StrPrintAsync(string str)
{
await Task.Run(() =>
{
// 输出日志的异步操作
//vLogBox.Text += "\r\n" + str;
MessageBox.Show(str);
StrPrint(str);
});
}
private void StrPrint(string str)
{
// 使用 Dispatcher 来确保在 UI 线程上执行更新操作
Dispatcher.Invoke(() =>
{
vLogBox.Text += "\r\n" + str;
// 将滚动条滚动到末尾
vLogBox.ScrollToEnd();
});
}
private void GetVal(int val)
{