智能路径ContactABOut 增加静态跳过功能
This commit is contained in:
parent
aa30959d71
commit
3a6de2e67f
@ -648,6 +648,36 @@ namespace FlightRouteV2
|
||||
return new_bVecs;
|
||||
}
|
||||
/// <summary>
|
||||
/// 从数组中删除指定索引处的元素
|
||||
/// </summary>
|
||||
/// <typeparam name="T">数组元素类型</typeparam>
|
||||
/// <param name="array">要操作的数组</param>
|
||||
/// <param name="indicesToRemove">要删除的元素的索引列表</param>
|
||||
/// <returns>删除元素后的新数组</returns>
|
||||
private static T[] RemoveElementsAtIndices<T>(T[] array, List<int> indicesToRemove)
|
||||
{
|
||||
// 检查索引是否有效
|
||||
if (indicesToRemove == null || indicesToRemove.Count == 0)
|
||||
{
|
||||
// 没有要删除的索引,返回原数组
|
||||
return array;
|
||||
}
|
||||
// 创建一个新数组,长度为原数组长度减去要删除的元素数量
|
||||
T[] newArray = new T[array.Length - indicesToRemove.Count];
|
||||
int newIndex = 0;
|
||||
// 复制不包括指定索引的元素到新数组中
|
||||
for (int i = 0; i < array.Length; i++)
|
||||
{
|
||||
if (!indicesToRemove.Contains(i))
|
||||
{
|
||||
newArray[newIndex] = array[i];
|
||||
newIndex++;
|
||||
}
|
||||
}
|
||||
// 返回新数组
|
||||
return newArray;
|
||||
}
|
||||
/// <summary>
|
||||
/// 设置中间航点
|
||||
/// </summary>
|
||||
/// <param name="aVec">起点</param>
|
||||
@ -730,7 +760,7 @@ namespace FlightRouteV2
|
||||
/// <param name="vec1">平面上的点1</param>
|
||||
/// <param name="vec2">平面上的点2</param>
|
||||
/// <param name="vec3">平面上的点3</param>
|
||||
/// <param name="vec4">垂直于平面的点</param>
|
||||
/// <param name="vec4">被求点</param>
|
||||
/// <returns>交点坐标</returns>
|
||||
private static Vector3 CalculateIntersectionPoint(Vector3 vec1, Vector3 vec2, Vector3 vec3, Vector3 vec4)
|
||||
{
|
||||
@ -841,7 +871,7 @@ namespace FlightRouteV2
|
||||
else return false;
|
||||
}
|
||||
/// <summary>
|
||||
/// 从顶视图 判断点是否在两条内之间
|
||||
/// 从顶视图 判断点是否在两条线内之间
|
||||
/// </summary>
|
||||
/// <param name="A">线段1端点</param>
|
||||
/// <param name="B">线段1端点</param>
|
||||
@ -1337,15 +1367,43 @@ namespace FlightRouteV2
|
||||
/// <param name="aVecs">起始点坐标组</param>
|
||||
/// <param name="bVecs">目标点坐标组</param>
|
||||
/// <param name="StrPrint">日志输出 回调函数</param>
|
||||
/// <param name="isStaticSkip">静态跳过 true跳过即保持原地不动 false不跳过参与“最近和交换”计算</param>
|
||||
/// <param name="staticThresholdSquare">静态距离判断 小于阈值判定为静态 注意是个平方值</param>
|
||||
/// <param name="isSwap">交叉航线是否进行交换</param>
|
||||
/// <param name="swapCount">交换次数</param>
|
||||
/// <param name="crossingLimit">交叉线路数量上限 ps:超过这个数量则不进行交换</param>
|
||||
/// <returns>新的目标点</returns>
|
||||
public static Vector3[] ContactABOut(Vector3[] aVecs, Vector3[] bVecs, SomeCalculateWay StrPrint, bool isSwap = true, int swapCount = 5, int crossingLimit = 6)
|
||||
public static Vector3[] ContactABOut(Vector3[] aVecs, Vector3[] bVecs, SomeCalculateWay StrPrint,bool isStaticSkip = true, double staticThresholdSquare = 25 , bool isSwap = true, int swapCount = 5, int crossingLimit = 6)
|
||||
{
|
||||
long t = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
|
||||
StrPrint("-------智能选择路径计算,开始-------");
|
||||
int planeCou = aVecs.Length; // 飞机总数
|
||||
List<int> staticAindex = new List<int>(); // a静态对应关系(ab两图同一位置)
|
||||
List<int> staticBindex = new List<int>(); // b静态对应关系(ab两图同一位置)
|
||||
Vector3[] new_aVecs = aVecs.ToArray(); //a图副本
|
||||
Vector3[] new_bVecs = bVecs.ToArray(); //b图副本
|
||||
///如果启动 静态航点跳过 把ab静态对应关系找出来 预存放到staticMatch
|
||||
if (isStaticSkip)
|
||||
{
|
||||
for (int i = 0; i < planeCou; i++)
|
||||
{
|
||||
for (int j = 0; j < planeCou; j++)
|
||||
{
|
||||
if (GageLengthSquare(aVecs[i], bVecs[j]) <= staticThresholdSquare)
|
||||
{
|
||||
staticAindex.Add(i);
|
||||
staticBindex.Add(j);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
//把静态的航点从列表里面清除
|
||||
new_aVecs = RemoveElementsAtIndices(new_aVecs, staticAindex);
|
||||
new_bVecs = RemoveElementsAtIndices(new_bVecs, staticBindex);
|
||||
//刷新飞机总数 以下计算最近 和 交换航线时候 只有非静态飞机参与
|
||||
planeCou = new_aVecs.Length;
|
||||
}
|
||||
|
||||
List<int[]> match = new List<int[]>(); // ab对应关系
|
||||
///记录a b集合索引
|
||||
List<int> aIndex = new List<int>();
|
||||
@ -1365,8 +1423,8 @@ namespace FlightRouteV2
|
||||
List<Vector3> allVecs = new List<Vector3>();
|
||||
for (int i = 0; i < remainCou; i++)
|
||||
{
|
||||
allVecs.Add(aVecs[aIndex[i]]);
|
||||
allVecs.Add(bVecs[bIndex[i]]);
|
||||
allVecs.Add(new_aVecs[aIndex[i]]);
|
||||
allVecs.Add(new_bVecs[bIndex[i]]);
|
||||
}
|
||||
Vector3 centerVec = GetPosCenter(allVecs);//重心点
|
||||
// 遍历所有ab点距离重心点的距离
|
||||
@ -1374,8 +1432,8 @@ namespace FlightRouteV2
|
||||
double[] bLens = new double[remainCou];
|
||||
for (int i = 0; i < remainCou; i++)
|
||||
{
|
||||
aLens[i] = GageLengthSquare(aVecs[aIndex[i]], centerVec);
|
||||
bLens[i] = GageLengthSquare(bVecs[bIndex[i]], centerVec);
|
||||
aLens[i] = GageLengthSquare(new_aVecs[aIndex[i]], centerVec);
|
||||
bLens[i] = GageLengthSquare(new_bVecs[bIndex[i]], centerVec);
|
||||
}
|
||||
// 找出ab集合最外层坐标的下标 即离重心点最远的点
|
||||
int aMaxIndex = GetIndexOfMaxOrMin(aLens); // a集合到重心点最长的距离 数组的下标
|
||||
@ -1385,7 +1443,7 @@ namespace FlightRouteV2
|
||||
double[] outAtoBLen = new double[remainCou];//最外层A点到 B集合所有点的距离
|
||||
for (int i = 0; i < remainCou; i++)
|
||||
{
|
||||
outAtoBLen[i] = GageLengthSquare(aVecs[aIndex[aMaxIndex]], bVecs[bIndex[i]]);
|
||||
outAtoBLen[i] = GageLengthSquare(new_aVecs[aIndex[aMaxIndex]], new_bVecs[bIndex[i]]);
|
||||
}
|
||||
int bMinIndex = GetIndexOfMaxOrMin(outAtoBLen, false);// 最短距离
|
||||
match.Add(new int[] { aIndex[aMaxIndex], bIndex[bMinIndex] });// 映射到配对
|
||||
@ -1397,7 +1455,7 @@ namespace FlightRouteV2
|
||||
double[] outBtoALen = new double[remainCou];//最外层B点到 A集合所有点的距离
|
||||
for (int i = 0; i < remainCou; i++)
|
||||
{
|
||||
outBtoALen[i] = GageLengthSquare(aVecs[aIndex[i]], bVecs[bIndex[bMaxIndex]]);
|
||||
outBtoALen[i] = GageLengthSquare(new_aVecs[aIndex[i]], new_bVecs[bIndex[bMaxIndex]]);
|
||||
}
|
||||
int aMinIndex = GetIndexOfMaxOrMin(outBtoALen, false);// 最短距离
|
||||
match.Add(new int[] { aIndex[aMinIndex], bIndex[bMaxIndex] });// 映射到配对
|
||||
@ -1405,77 +1463,95 @@ namespace FlightRouteV2
|
||||
bIndex.RemoveAt(bMaxIndex); // 删除已经配对的b集合 ID
|
||||
}
|
||||
}
|
||||
Vector3[] new_bVecs = CreateNewBVecs(bVecs, match);// 按照映射 获取a 对应的 新的b集合
|
||||
if (!isSwap)
|
||||
{
|
||||
return new_bVecs;
|
||||
}
|
||||
Vector3[] re_bVecs = CreateNewBVecs(new_bVecs, match);// 按照映射 获取a 对应的 新的b集合
|
||||
///交叉 交换
|
||||
for (int i = 0; i < swapCount; i++)
|
||||
if (isSwap)
|
||||
{
|
||||
List<int[]> planesCollision = AirImitation(aVecs, new_bVecs);// 获取碰撞组
|
||||
List<List<int>> formatCollision = FindConnected(planesCollision);// 获取交叉序列 例如:[[0,2][0,3][3,4][5,6]] 结果[[0,2,3,4][5,6]]
|
||||
List<List<int>> filteredCollision = formatCollision.Where(sublist => sublist.Count <= crossingLimit).ToList();// 过滤 只保留交叉数量小于等于crossingLimit的序列
|
||||
if (filteredCollision.Count == 0) break;
|
||||
///日志输出
|
||||
string log = "";
|
||||
foreach (List<int> item in filteredCollision)
|
||||
for (int i = 0; i < swapCount; i++)
|
||||
{
|
||||
log += "[";
|
||||
foreach (int itemInt in item)
|
||||
List<int[]> planesCollision = AirImitation(new_aVecs, re_bVecs);// 获取碰撞组
|
||||
List<List<int>> formatCollision = FindConnected(planesCollision);// 获取交叉序列 例如:[[0,2][0,3][3,4][5,6]] 结果[[0,2,3,4][5,6]]
|
||||
List<List<int>> filteredCollision = formatCollision.Where(sublist => sublist.Count <= crossingLimit).ToList();// 过滤 只保留交叉数量小于等于crossingLimit的序列
|
||||
if (filteredCollision.Count == 0) break;
|
||||
///日志输出
|
||||
string log = "";
|
||||
foreach (List<int> item in filteredCollision)
|
||||
{
|
||||
log += $"{itemInt},";
|
||||
log += "[";
|
||||
foreach (int itemInt in item)
|
||||
{
|
||||
log += $"{itemInt},";
|
||||
}
|
||||
log += "]";
|
||||
}
|
||||
log += "]";
|
||||
}
|
||||
StrPrint($"共迭代{swapCount}次交换,第{i}次。共{filteredCollision.Count}组,交换组为:{log}。");
|
||||
/// 遍历所有交叉组 分组做交换
|
||||
int cou = 0;
|
||||
foreach (List<int> swap_indices in filteredCollision)
|
||||
{
|
||||
cou++;
|
||||
StrPrint($"进度:{cou}/{filteredCollision.Count}。交换组:[{string.Join(", ", swap_indices)}]。");
|
||||
///交叉 生成所有排列
|
||||
List<List<int>> all_permutations = Permutations(swap_indices);//所有排列组合
|
||||
List<int> original = all_permutations[0];//原始排列
|
||||
all_permutations.RemoveAt(0);//删掉第一个 既原始排列
|
||||
/// 按所有的排列 互换航线 并检测出最佳的对应目标点
|
||||
List<int> tempLen = new List<int>(); //记录最少碰撞的 排列
|
||||
List<Vector3[]> tempNew_bVecsS = new List<Vector3[]>();//记录最少碰撞的 排列交换之后的目标坐标集
|
||||
foreach (List<int> indices in all_permutations)
|
||||
StrPrint($"共迭代{swapCount}次交换,第{i}次。共{filteredCollision.Count}组,交换组为:{log}。");
|
||||
/// 遍历所有交叉组 分组做交换
|
||||
int cou = 0;
|
||||
foreach (List<int> swap_indices in filteredCollision)
|
||||
{
|
||||
Vector3[] current_array = new Vector3[planeCou];
|
||||
Array.Copy(new_bVecs, current_array, planeCou);//复制一个new_bVecs 副本
|
||||
for (int k = 0; k < indices.Count; k++)
|
||||
cou++;
|
||||
StrPrint($"进度:{cou}/{filteredCollision.Count}。交换组:[{string.Join(", ", swap_indices)}]。");
|
||||
///交叉 生成所有排列
|
||||
List<List<int>> all_permutations = Permutations(swap_indices);//所有排列组合
|
||||
List<int> original = all_permutations[0];//原始排列
|
||||
all_permutations.RemoveAt(0);//删掉第一个 既原始排列
|
||||
/// 按所有的排列 互换航线 并检测出最佳的对应目标点
|
||||
List<int> tempLen = new List<int>(); //记录最少碰撞的 排列
|
||||
List<Vector3[]> tempNew_bVecsS = new List<Vector3[]>();//记录最少碰撞的 排列交换之后的目标坐标集
|
||||
foreach (List<int> indices in all_permutations)
|
||||
{
|
||||
current_array[original[k]] = new_bVecs[indices[k]];
|
||||
}
|
||||
///把最少碰撞的排列 录入到数组
|
||||
int collisionsCou = (AirImitation(aVecs, current_array)).Count;//此排列的碰撞次数
|
||||
if (tempLen.Count == 0 || tempLen[0] == collisionsCou)//如果第一次添加 或者 碰撞次数等于最少碰撞
|
||||
{
|
||||
///录入数组
|
||||
tempLen.Add(collisionsCou);
|
||||
tempNew_bVecsS.Add(current_array);
|
||||
}
|
||||
else if (tempLen[0] > collisionsCou)
|
||||
{
|
||||
/// 如果最小值 大于 当前碰撞次数,清空之前记录
|
||||
tempLen.Clear();
|
||||
tempNew_bVecsS.Clear();
|
||||
///录入数组
|
||||
tempLen.Add(collisionsCou);
|
||||
tempNew_bVecsS.Add(current_array);
|
||||
Vector3[] current_array = new Vector3[planeCou];
|
||||
Array.Copy(re_bVecs, current_array, planeCou);//复制一个re_bVecs 副本
|
||||
for (int k = 0; k < indices.Count; k++)
|
||||
{
|
||||
current_array[original[k]] = re_bVecs[indices[k]];
|
||||
}
|
||||
///把最少碰撞的排列 录入到数组
|
||||
int collisionsCou = (AirImitation(new_aVecs, current_array)).Count;//此排列的碰撞次数
|
||||
if (tempLen.Count == 0 || tempLen[0] == collisionsCou)//如果第一次添加 或者 碰撞次数等于最少碰撞
|
||||
{
|
||||
///录入数组
|
||||
tempLen.Add(collisionsCou);
|
||||
tempNew_bVecsS.Add(current_array);
|
||||
}
|
||||
else if (tempLen[0] > collisionsCou)
|
||||
{
|
||||
/// 如果最小值 大于 当前碰撞次数,清空之前记录
|
||||
tempLen.Clear();
|
||||
tempNew_bVecsS.Clear();
|
||||
///录入数组
|
||||
tempLen.Add(collisionsCou);
|
||||
tempNew_bVecsS.Add(current_array);
|
||||
}
|
||||
}
|
||||
re_bVecs = tempNew_bVecsS[GetRandomMinIndex(tempLen)];
|
||||
}
|
||||
new_bVecs = tempNew_bVecsS[GetRandomMinIndex(tempLen)];
|
||||
}
|
||||
}
|
||||
|
||||
///静态飞机 赋值回 返回航点组 ps:航点赋值的位置是对应的a组的ID位置 映射到b组的位置
|
||||
if (isStaticSkip)
|
||||
{
|
||||
planeCou = aVecs.Length;
|
||||
List<Vector3> re_bVecsCopy = new List<Vector3>(re_bVecs);
|
||||
List<Vector3> re_bVecsList = new List<Vector3>();
|
||||
for (int i = 0; i < planeCou; i++)
|
||||
{
|
||||
if (staticAindex.IndexOf(i) != -1)
|
||||
{
|
||||
re_bVecsList.Add(aVecs[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
re_bVecsList.Add(re_bVecsCopy[0]);
|
||||
re_bVecsCopy.RemoveAt(0);
|
||||
}
|
||||
}
|
||||
re_bVecs = re_bVecsList.ToArray();
|
||||
}
|
||||
t = DateTimeOffset.UtcNow.ToUnixTimeSeconds() - t;
|
||||
StrPrint($"用时:{t}秒");
|
||||
StrPrint($"-------智能选择路径计算,结束-------");
|
||||
return new_bVecs;
|
||||
return re_bVecs;
|
||||
}
|
||||
/// <summary>
|
||||
/// 智能错层
|
||||
@ -1504,19 +1580,21 @@ namespace FlightRouteV2
|
||||
Vector3[] new_aVecs = aVecs.ToArray(); //a图副本
|
||||
Vector3[] new_bVecs = bVecs.ToArray(); //b图副本
|
||||
|
||||
///把所有点压在 最“共面”上
|
||||
///把所有点压在 主面“共面”上
|
||||
List<int> maxVecsOfCoplane = FindMaxPlaneIndices(aVecs);// 找出A图共面最多点的索引
|
||||
StrPrint("正在进行“共面”检测,需要一些时间请耐心等待。。。");
|
||||
if (maxVecsOfCoplane.Count < 4) //a图至少要有4个点 共面
|
||||
{
|
||||
StrPrint("a图案至少有4个点以上共面,否则不可执行错层处理");
|
||||
StrPrint($"-------错层结束-------");
|
||||
return re;
|
||||
}
|
||||
//共面上取三个点
|
||||
///共面上取三个点
|
||||
Vector3 vec0 = new_aVecs[maxVecsOfCoplane[0]];
|
||||
Vector3 vec1 = new_aVecs[maxVecsOfCoplane[1]];
|
||||
Vector3 vec2 = new_aVecs[maxVecsOfCoplane[2]];
|
||||
for (int i = 0; i < planeCou; i++) //遍历 把a图和b图点压到 “共面”上
|
||||
///遍历 把a图和b图点压到 “共面”上
|
||||
for (int i = 0; i < planeCou; i++)
|
||||
{
|
||||
if (!(maxVecsOfCoplane.Contains(i))) //除去在共面内的面
|
||||
{
|
||||
@ -1979,7 +2057,7 @@ namespace FlightRouteV2
|
||||
/// <param name="bVecs">回归矩阵坐标组</param>
|
||||
/// <param name="strPrint">日志输出 回调函数</param>
|
||||
/// <returns>拉散图案的坐标组</returns>
|
||||
public static Vector3[] NormalPull(Vector3[] aVecs, Vector3[] bVecs, SomeCalculateWay StrPrint)
|
||||
public static Vector3[] NormalPull(Vector3[] aVecs, Vector3[] bVecs, SomeCalculateWay StrPrint,double pullingDistance = 300)
|
||||
{
|
||||
Vector3[] new_aVecs = aVecs.ToArray(); //a图副本
|
||||
Vector3[] new_bVecs = bVecs.ToArray(); //矩阵副本
|
||||
@ -2036,11 +2114,11 @@ namespace FlightRouteV2
|
||||
///判断图在矩阵的左方 还是右方
|
||||
if (GageLength(aCenterPos, new_bVecs[0]) > GageLength(aCenterPos, new_bVecs[row - 1]))
|
||||
{
|
||||
new_aVecs[cou] -= normalScalar * (row - k) * 300;//左方
|
||||
new_aVecs[cou] -= normalScalar * (row - k) * pullingDistance;//左方
|
||||
}
|
||||
else
|
||||
{
|
||||
new_aVecs[cou] += normalScalar * k * 300;//右方
|
||||
new_aVecs[cou] += normalScalar * k * pullingDistance;//右方
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2079,11 +2157,11 @@ namespace FlightRouteV2
|
||||
///判断图在矩阵的上方 还是下方
|
||||
if (GageLength(aCenterPos, new_bVecs[0]) > GageLength(aCenterPos, new_bVecs[row * (ran - 1)]))
|
||||
{
|
||||
new_aVecs[cou] -= normalScalar * (ran - k) * 300;//上方
|
||||
new_aVecs[cou] -= normalScalar * (ran - k) * pullingDistance;//上方
|
||||
}
|
||||
else
|
||||
{
|
||||
new_aVecs[cou] += normalScalar * k * 300;//下方
|
||||
new_aVecs[cou] += normalScalar * k * pullingDistance;//下方
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -73,6 +73,7 @@ namespace FlyCube
|
||||
File.Delete(pathd);
|
||||
}
|
||||
SaveFile(pathd, txtd);
|
||||
|
||||
}
|
||||
/// <summary>
|
||||
/// 3D绕行
|
||||
@ -88,11 +89,11 @@ 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_aVecs = FlyVecFun.NormalPull(aVecs, bVecs, StrPrintAsync);
|
||||
//Vector3[] new_bVecs = FlyVecFun.ContactABOut(aVecs, bVecs, StrPrint);
|
||||
Vector3[] new_aVecs = FlyVecFun.NormalPull(aVecs, bVecs, StrPrintAsync);
|
||||
|
||||
bool isPass;
|
||||
Task<List<List<Vector3>>> reTask = Task.Run(() => FlyVecFun.ABypassB(aVecs, bVecs, StrPrintAsync, GetVal, cts.Token, out isPass));
|
||||
Task<List<List<Vector3>>> reTask = Task.Run(() => FlyVecFun.ABypassB(new_aVecs, bVecs, StrPrintAsync, GetVal, cts.Token, out isPass));
|
||||
List<List<Vector3>> re = await reTask;
|
||||
|
||||
string txta = "";
|
||||
@ -114,7 +115,7 @@ namespace FlyCube
|
||||
{
|
||||
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";
|
||||
txtd += i + " 0" + " " + new_aVecs[i].X + " " + new_aVecs[i].Y + " " + new_aVecs[i].Z + "\r\n";
|
||||
|
||||
}
|
||||
if (re.Count > 0)
|
||||
|
Loading…
Reference in New Issue
Block a user