diff --git a/FlieOperate/FileBase.cs b/FlieOperate/FileBase.cs
index 3edce87..57c83da 100644
--- a/FlieOperate/FileBase.cs
+++ b/FlieOperate/FileBase.cs
@@ -1,9 +1,10 @@
-using System;
+using FlyBase;
+using System;
+using System.Collections;
using System.Collections.Generic;
using System.IO;
-using System.Linq;
using System.Text;
-using System.Threading.Tasks;
+using System.Text.RegularExpressions;
using System.Windows.Forms;
namespace FlieOperate
@@ -13,6 +14,204 @@ namespace FlieOperate
///
public class FileBase
{
+ ///
+ /// 逐行读取 文档
+ ///
+ /// 文件路径
+ ///
+ private static string[] ReadFile(string path)
+ {
+ StreamReader sr = new StreamReader(path, Encoding.Default);
+ String line;
+ ArrayList arrlist = new ArrayList();
+ while ((line = sr.ReadLine()) != null)
+ {
+ arrlist.Add(line);
+ }
+ if (arrlist.Count == 1)//判断 svg的文件内容 是否写在一行里面
+ {
+ string temp = (string)arrlist[0];
+ string[] strArray = Regex.Split(temp, "/>");
+ return strArray;
+ }
+ string[] arr = new string[arrlist.Count];
+ int key = 0;
+ foreach (var item in arrlist)
+ {
+ arr[key] = (string)item;
+ key++;
+ }
+ return arr;
+ }
+ ///
+ /// svg航点坐标文档 转坐标集合 PS:灯光映射 支持格式
+ ///
+ /// 文件路径
+ ///
+ public static Vector3[] SvgToPosForLight(string path)
+ {
+ //读取文档内容
+ string[] arr;
+ arr = ReadFile(path);
+ //获取飞机x轴 z轴 坐标
+ ArrayList tempVec = new ArrayList();//记录飞机坐标
+ string cx = @"cx=""(?\-{0,1}\d*\.{0,1}\d*)""";
+ string cy = @"cy=""(?\-{0,1}\d*\.{0,1}\d*)""";
+ string r = @"r=""(?\d*\.{0,1}\d*)""";
+ foreach (string item in arr)
+ {
+ if (item.IndexOf("= 0)//找到svg里面标签
+ {
+ Regex reg = new Regex(cx);
+ string strX = reg.Match(item).Groups["mark"].ToString();//正则匹配获取x轴
+ reg = new Regex(cy);
+ string strZ = reg.Match(item).Groups["mark"].ToString();//正则匹配获取y轴 在三维里面用作z轴
+ double x = Convert.ToDouble(strX);
+ double z = Convert.ToDouble(strZ);
+ tempVec.Add(new Vector3(x, 0, z));
+ }
+ }
+ Vector3[] vec = FlyVecFun.ArrToVec(tempVec);//把arrlist转换成坐标集合
+ return vec;//返回坐标集合
+ }
+ ///
+ /// txt航点坐标文档 转坐标集合 PS:目前是C4D坐标文档
+ ///
+ /// 文件路径
+ /// 参数形式返回航点名称集合
+ /// 航点集合
+ public static List TxtToPos(string path, out string[] flightPointNames)
+ {
+ //读取文档内容
+ string[] arr;
+ arr = ReadFile(path);
+ //处理文档内容
+ int group = 0;//获取有几组坐标
+ foreach (string item in arr)
+ {
+ if (item.IndexOf(" ") <= 0)//找到航点名称
+ {
+ group++;
+ }
+ }
+ int planesCou = (arr.Length - group) / group;//获取飞机总数
+ flightPointNames = new string[group];//记录航点名称
+ int gKey = 0;//航点名称数组下标
+ int pKey = 0;//所有坐标序号
+ Vector3[] pos = new Vector3[planesCou];//临时记录飞机坐标
+ List re = new List();//返回值
+ for (int i = 0; i < arr.Length; i++)
+ {
+ if (i % (planesCou + 1) == 0)//分析是否是航点名称 行
+ {
+ flightPointNames[gKey] = arr[i];//记录航点名称
+ gKey++;
+ }
+ else//否则 当坐标行处理
+ {
+ string[] tempArr = arr[i].Split(' ');//每行坐标分割
+ pos[pKey % planesCou] = new Vector3(Convert.ToDouble(tempArr[1]), Convert.ToDouble(tempArr[2]), Convert.ToDouble(tempArr[3]));
+ if (pKey % planesCou == planesCou - 1)//当一组组标循环完成 之后记录到返回组
+ {
+ re.Add(pos);
+ pos = new Vector3[planesCou];//重新new一下 更新内存地址
+ }
+ pKey++;
+ }
+ }
+ return re;//out flightPointNames 输出航点名称,re返回值 返回航点集合
+ }
+ ///
+ /// svg航点坐标文档 转坐标集合
+ ///
+ /// 文件路径
+ /// 坐标集合
+ public static Vector3[] SvgToPos(string path)
+ {
+ //读取文档内容
+ string[] arr;
+ arr = ReadFile(path);
+ //获取飞机x轴 z轴 坐标
+ ArrayList tempVec = new ArrayList();//记录飞机坐标
+ string cx = @"cx=""(?\-{0,1}\d*\.{0,1}\d*)""";
+ string cy = @"cy=""(?\-{0,1}\d*\.{0,1}\d*)""";
+ string r = @"r=""(?\d*\.{0,1}\d*)""";
+ foreach (string item in arr)
+ {
+ if (item.IndexOf("= 0)//找到svg里面标签
+ {
+ Regex reg = new Regex(cx);
+ string strX = reg.Match(item).Groups["mark"].ToString();//正则匹配获取x轴
+ reg = new Regex(cy);
+ string strZ = reg.Match(item).Groups["mark"].ToString();//正则匹配获取y轴 在三维里面用作z轴
+ reg = new Regex(r);
+ string radius = reg.Match(item).Groups["mark"].ToString();//正则匹配获取球半径
+ //按比例缩放(半径为100公分) 获取世界坐标
+ double Rate = 100 / Convert.ToDouble(radius);
+ double x = Rate * Convert.ToDouble(strX);
+ double z = Rate * Convert.ToDouble(strZ) * -1;
+ tempVec.Add(new Vector3(x, 0, z));
+ }
+ }
+ //坐标集原点相对位置 移到坐标集质心
+ Vector3[] vec = FlyVecFun.ArrToVec(tempVec);//把arrlist转换成坐标集合
+ Vector3 centerPos = FlyVecFun.GetPosCenter(vec);//获取中心点
+ int key = 0;
+ foreach (Vector3 item in vec)
+ {
+ item.SetZero(centerPos);
+ vec[key] = item;
+ key++;
+ }
+ return vec;//返回坐标集合
+ }
+ ///
+ /// obj航点坐标文档 转坐标集合
+ ///
+ /// 文件路径
+ /// 坐标集合
+ public static Vector3[] ObjToPos(string path)
+ {
+ //读取文档内容
+ string[] arr;
+ arr =ReadFile(path);
+ //获取飞机x轴 z轴 坐标
+ string pCou = @"#\s+(?\d*)\s+vertices";//匹配obj里面标记点的数量
+ string pPos = @"v\s+(?\-{0,1}\d*\.{0,1}\d*)\s+(?\-{0,1}\d*\.{0,1}\d*)\s+(?\-{0,1}\d*\.{0,1}\d*)";
+ int linage = 0;//行数
+ string tempPos;//临时记录一下 xyz坐标
+ ArrayList tempVec = new ArrayList();//记录飞机坐标
+ foreach (string item in arr)
+ {
+ Regex reg = new Regex(pCou);
+ string cou = reg.Match(item).Groups["mark"].ToString();//正则匹配获取x轴
+ if (cou != "")
+ {
+ for (int i = Convert.ToInt32(cou); i > 0; i--)
+ {
+ tempPos = arr[linage - i];
+ reg = new Regex(pPos);
+ string strX = reg.Match(tempPos).Groups["markX"].ToString();
+ string strY = reg.Match(tempPos).Groups["markY"].ToString();
+ string strZ = reg.Match(tempPos).Groups["markZ"].ToString();
+ tempVec.Add(new Vector3(Convert.ToDouble(strX), Convert.ToDouble(strY), Convert.ToDouble(strZ)));
+ }
+ }
+ linage++;
+ }
+ //坐标集原点相对位置 移到坐标集质心
+ Vector3[] vec = FlyVecFun.ArrToVec(tempVec);//把arrlist转换成坐标集合
+ //重新定义中心点为原点
+ //Vector3 centerPos = getPosCenter(vec);//获取中心点
+ //int key = 0;
+ //foreach (Vector3 item in vec)
+ //{
+ // item.setZero(centerPos);
+ // vec[key] = item;
+ // key++;
+ //}
+ return vec;//返回坐标集合
+ }
///
/// 资源管理器 文件类型 中文说明 和扩展名是 成对关系 数组长度要一致
///
diff --git a/FlieOperate/FlieOperate.csproj b/FlieOperate/FlieOperate.csproj
index e509561..768baff 100644
--- a/FlieOperate/FlieOperate.csproj
+++ b/FlieOperate/FlieOperate.csproj
@@ -31,6 +31,9 @@
4
+
+ ..\FlyCube\bin\Release\FlyBase.dll
+
..\FlyCube\packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll
diff --git a/FlieOperate/Properties/AssemblyInfo.cs b/FlieOperate/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..62ce263
--- /dev/null
+++ b/FlieOperate/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// 有关程序集的一般信息由以下
+// 控制。更改这些特性值可修改
+// 与程序集关联的信息。
+[assembly: AssemblyTitle("FlieOperate")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("FlieOperate")]
+[assembly: AssemblyCopyright("Copyright © 2022")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// 将 ComVisible 设置为 false 会使此程序集中的类型
+//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
+//请将此类型的 ComVisible 特性设置为 true。
+[assembly: ComVisible(false)]
+
+// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
+[assembly: Guid("c354fd6b-5863-4246-bb48-6df14a85c161")]
+
+// 程序集的版本信息由下列四个值组成:
+//
+// 主版本
+// 次版本
+// 生成号
+// 修订号
+//
+//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
+//通过使用 "*",如下所示:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/FlieOperate/packages.config b/FlieOperate/packages.config
new file mode 100644
index 0000000..5eaa239
--- /dev/null
+++ b/FlieOperate/packages.config
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/FlyBase/FlyBase.cs b/FlyBase/FlyBase.cs
index 1daffd4..8249903 100644
--- a/FlyBase/FlyBase.cs
+++ b/FlyBase/FlyBase.cs
@@ -1,20 +1,127 @@
-using System;
+using Microsoft.SqlServer.Server;
+using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
+using System.Net.Http;
+using System.Net.NetworkInformation;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Security.Cryptography;
+using System.Security.Policy;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Documents;
+using System.Windows.Shapes;
+using static System.Net.WebRequestMethods;
namespace FlyBase
{
+ //矩阵类
+ public struct Matrix
+ {
+ public double M11, M12, M13;
+ public double M21, M22, M23;
+ public double M31, M32, M33;
+ public double M41, M42, M43;
+ ///
+ /// 构造函数,接受四个 Vector3 对象
+ ///
+ /// 向量1
+ /// 向量2
+ /// 向量3
+ /// 向量4
+ public Matrix(Vector3 row1, Vector3 row2, Vector3 row3, Vector3 row4)
+ {
+ M11 = row1.X; M12 = row1.Y; M13 = row1.Z;
+ M21 = row2.X; M22 = row2.Y; M23 = row2.Z;
+ M31 = row3.X; M32 = row3.Y; M33 = row3.Z;
+ M41 = row4.X; M42 = row4.Y; M43 = row4.Z;
+ }
+ ///
+ /// 通过方法实现通过索引的访问
+ ///
+ ///
+ public Vector3 this[int index]
+ {
+ get
+ {
+ switch (index)
+ {
+ case 0: return new Vector3(M11, M12, M13);
+ case 1: return new Vector3(M21, M22, M23);
+ case 2: return new Vector3(M31, M32, M33);
+ case 3: return new Vector3(M41, M42, M43);
+ default:
+ throw new IndexOutOfRangeException("Index out of range for Matrix");
+ }
+ }
+ }
+ ///
+ /// // 重写 ToString 方法,以便能够直接打印矩阵
+ ///
+ public override string ToString()
+ {
+ return $"v1:{M11}, {M12}, {M13}\n" +
+ $"v2:{M21}, {M22}, {M23}\n" +
+ $"v3:{M31}, {M32}, {M33}\n" +
+ $"off:{M41}, {M42}, {M43}";
+ }
+ }
+ //向量类
public struct Vector3
{
public double X { get; set; }
public double Y { get; set; }
public double Z { get; set; }
///
+ /// [数组下标]方式 访问XYZ属性
+ ///
+ ///
+ /// [0]X [1]Y [2]Z
+ /// 访问下标0-2
+ public double this[int index]
+ {
+ get
+ {
+ switch (index)
+ {
+ case 0:
+ return X;
+ case 1:
+ return Y;
+ case 2:
+ return Z;
+ default:
+ throw new IndexOutOfRangeException($"Index {index} is out of range for Vector3");
+ }
+ }
+ set
+ {
+ switch (index)
+ {
+ case 0:
+ X = value;
+ break;
+ case 1:
+ Y = value;
+ break;
+ case 2:
+ Z = value;
+ break;
+ default:
+ throw new IndexOutOfRangeException($"Index {index} is out of range for Vector3");
+ }
+ }
+ }
+ // 静态属性表示单位向量
+ public static Vector3 UnitX { get { return new Vector3(1.0, 0.0, 0.0); } }
+ public static Vector3 UnitY { get { return new Vector3(0.0, 1.0, 0.0); } }
+ public static Vector3 UnitZ { get { return new Vector3(0.0, 0.0, 1.0); } }
+ ///
/// 构造 初始化
///
/// x坐标
@@ -149,6 +256,41 @@ namespace FlyBase
return false;
}
///
+ /// 确定指定的对象是否等于当前向量。
+ ///
+ /// 要与当前向量比较的对象。
+ /// 如果指定的对象等于当前向量,则为 true;否则为 false。
+ public override bool Equals(object obj)
+ {
+ // 检查对象是否与当前向量具有相同的类型
+ if (obj is Vector3 vector)
+ {
+ // 比较向量的每个分量
+ return X == vector.X &&
+ Y == vector.Y &&
+ Z == vector.Z;
+ }
+
+ // 如果对象不是 Vector3 类型,则它们不相等
+ return false;
+ }
+ ///
+ /// 向量按矩阵旋转和偏移
+ ///
+ /// 矩阵
+ /// 返回一个新的向量
+ public Vector3 Multiply(Matrix mat)
+ {
+ Vector3 re = new Vector3();
+ //矩阵相乘 ps:旋转角度
+ re.X = this.X * mat[1].X + this.Y * mat[2].X + this.Z * mat[0].X;
+ re.Y = this.X * mat[1].Y + this.Y * mat[2].Y + this.Z * mat[0].Y;
+ re.Z = this.X * mat[1].Z + this.Y * mat[2].Z + this.Z * mat[0].Z;
+ //off偏移
+ re = re + mat[3];
+ return re;
+ }
+ ///
/// 求模长
///
/// 向量到原点的模长
@@ -157,6 +299,14 @@ namespace FlyBase
return Math.Sqrt(Math.Pow(this.X, 2) + Math.Pow(this.Y, 2) + Math.Pow(this.Z, 2));
}
///
+ /// 求模长 平方
+ ///
+ /// 向量到原点的模长的平方值
+ public double GetMagSquared()
+ {
+ return Math.Pow(this.X, 2) + Math.Pow(this.Y, 2) + Math.Pow(this.Z, 2);
+ }
+ ///
/// 标准化坐标 无返回值 直接改变愿坐标
///
/// 标准化单位
@@ -220,203 +370,43 @@ namespace FlyBase
this.Z += v2.Z;
}
///
- /// 打印坐标
+ /// 重写ToString 打印坐标
///
/// 坐标字符串
- public string PosToString()
+ public override string ToString()
{
string x = Convert.ToString(this.X);
string y = Convert.ToString(this.Y);
string z = Convert.ToString(this.Z);
return string.Format($"X轴:{x} Y轴:{y} Z轴:{z}");
}
+ ///
+ /// 哈希码是一个整数值,用于对对象进行快速比较和索引
+ ///
+ /// 哈希码
+ public override int GetHashCode()
+ {
+ int hashCode = -307843816;
+ hashCode = hashCode * -1521134295 + X.GetHashCode();
+ hashCode = hashCode * -1521134295 + Y.GetHashCode();
+ hashCode = hashCode * -1521134295 + Z.GetHashCode();
+ return hashCode;
+ }
}
//坐标操作与验证
public static class FlyVecFun
{
- //逐行读取 文档
- private static string[] ReadFile(string path)
- {
- StreamReader sr = new StreamReader(path, Encoding.Default);
- String line;
- ArrayList arrlist = new ArrayList();
- while ((line = sr.ReadLine()) != null)
- {
- arrlist.Add(line);
- }
- if (arrlist.Count == 1)//判断 svg的文件内容 是否写在一行里面
- {
- string temp = (string)arrlist[0];
- string[] strArray = Regex.Split(temp, "/>");
- return strArray;
- }
- string[] arr = new string[arrlist.Count];
- int key = 0;
- foreach (var item in arrlist)
- {
- arr[key] = (string)item;
- key++;
- }
- return arr;
- }
- //svg航点坐标文档 转坐标集合 PS:灯光映射 支持格式
- public static Vector3[] SvgToPosForLight(string path)
- {
- //读取文档内容
- string[] arr;
- arr = FlyVecFun.ReadFile(path);
- //获取飞机x轴 z轴 坐标
- ArrayList tempVec = new ArrayList();//记录飞机坐标
- string cx = @"cx=""(?\-{0,1}\d*\.{0,1}\d*)""";
- string cy = @"cy=""(?\-{0,1}\d*\.{0,1}\d*)""";
- string r = @"r=""(?\d*\.{0,1}\d*)""";
- foreach (string item in arr)
- {
- if (item.IndexOf("= 0)//找到svg里面标签
- {
- Regex reg = new Regex(cx);
- string strX = reg.Match(item).Groups["mark"].ToString();//正则匹配获取x轴
- reg = new Regex(cy);
- string strZ = reg.Match(item).Groups["mark"].ToString();//正则匹配获取y轴 在三维里面用作z轴
- double x = Convert.ToDouble(strX);
- double z = Convert.ToDouble(strZ);
- tempVec.Add(new Vector3(x, 0, z));
- }
- }
- Vector3[] vec = ArrToVec(tempVec);//把arrlist转换成坐标集合
- return vec;//返回坐标集合
- }
- //txt航点坐标文档 转坐标集合 PS:目前是C4D坐标文档
- public static List TxtToPos(string path, out string[] flightPointNames)
- {
- //读取文档内容
- string[] arr;
- arr = FlyVecFun.ReadFile(path);
- //处理文档内容
- int group = 0;//获取有几组坐标
- foreach (string item in arr)
- {
- if (item.IndexOf(" ") <= 0)//找到航点名称
- {
- group++;
- }
- }
- int planesCou = (arr.Length - group) / group;//获取飞机总数
- flightPointNames = new string[group];//记录航点名称
- int gKey = 0;//航点名称数组下标
- int pKey = 0;//所有坐标序号
- Vector3[] pos = new Vector3[planesCou];//临时记录飞机坐标
- List re = new List();//返回值
- for (int i = 0; i < arr.Length; i++)
- {
- if (i % (planesCou + 1) == 0)//分析是否是航点名称 行
- {
- flightPointNames[gKey] = arr[i];//记录航点名称
- gKey++;
- }
- else//否则 当坐标行处理
- {
- string[] tempArr = arr[i].Split(' ');//每行坐标分割
- pos[pKey % planesCou] = new Vector3(Convert.ToDouble(tempArr[1]), Convert.ToDouble(tempArr[2]), Convert.ToDouble(tempArr[3]));
- if (pKey % planesCou == planesCou - 1)//当一组组标循环完成 之后记录到返回组
- {
- re.Add(pos);
- pos = new Vector3[planesCou];//重新new一下 更新内存地址
- }
- pKey++;
- }
- }
- return re;//out flightPointNames 输出航点名称,re返回值 返回航点集合
- }
- //svg航点坐标文档 转坐标集合
- public static Vector3[] SvgToPos(string path)
- {
- //读取文档内容
- string[] arr;
- arr = FlyVecFun.ReadFile(path);
- //获取飞机x轴 z轴 坐标
- ArrayList tempVec = new ArrayList();//记录飞机坐标
- string cx = @"cx=""(?\-{0,1}\d*\.{0,1}\d*)""";
- string cy = @"cy=""(?\-{0,1}\d*\.{0,1}\d*)""";
- string r = @"r=""(?\d*\.{0,1}\d*)""";
- foreach (string item in arr)
- {
- if (item.IndexOf("= 0)//找到svg里面标签
- {
- Regex reg = new Regex(cx);
- string strX = reg.Match(item).Groups["mark"].ToString();//正则匹配获取x轴
- reg = new Regex(cy);
- string strZ = reg.Match(item).Groups["mark"].ToString();//正则匹配获取y轴 在三维里面用作z轴
- reg = new Regex(r);
- string radius = reg.Match(item).Groups["mark"].ToString();//正则匹配获取球半径
- //按比例缩放(半径为100公分) 获取世界坐标
- double Rate = 100 / Convert.ToDouble(radius);
- double x = Rate * Convert.ToDouble(strX);
- double z = Rate * Convert.ToDouble(strZ) * -1;
- tempVec.Add(new Vector3(x, 0, z));
- }
- }
- //坐标集原点相对位置 移到坐标集质心
- Vector3[] vec = ArrToVec(tempVec);//把arrlist转换成坐标集合
- Vector3 centerPos = GetPosCenter(vec);//获取中心点
- int key = 0;
- foreach (Vector3 item in vec)
- {
- item.SetZero(centerPos);
- vec[key] = item;
- key++;
- }
- return vec;//返回坐标集合
- }
- //obj航点坐标文档 转坐标集合
- public static Vector3[] ObjToPos(string path)
- {
- //读取文档内容
- string[] arr;
- arr = FlyVecFun.ReadFile(path);
- //获取飞机x轴 z轴 坐标
- string pCou = @"#\s+(?\d*)\s+vertices";//匹配obj里面标记点的数量
- string pPos = @"v\s+(?\-{0,1}\d*\.{0,1}\d*)\s+(?\-{0,1}\d*\.{0,1}\d*)\s+(?\-{0,1}\d*\.{0,1}\d*)";
- int linage = 0;//行数
- string tempPos;//临时记录一下 xyz坐标
- ArrayList tempVec = new ArrayList();//记录飞机坐标
- foreach (string item in arr)
- {
- Regex reg = new Regex(pCou);
- string cou = reg.Match(item).Groups["mark"].ToString();//正则匹配获取x轴
- if (cou != "")
- {
- for (int i = Convert.ToInt32(cou); i > 0; i--)
- {
- tempPos = arr[linage - i];
- reg = new Regex(pPos);
- string strX = reg.Match(tempPos).Groups["markX"].ToString();
- string strY = reg.Match(tempPos).Groups["markY"].ToString();
- string strZ = reg.Match(tempPos).Groups["markZ"].ToString();
- tempVec.Add(new Vector3(Convert.ToDouble(strX), Convert.ToDouble(strY), Convert.ToDouble(strZ)));
- }
- }
- linage++;
- }
- //坐标集原点相对位置 移到坐标集质心
- Vector3[] vec = ArrToVec(tempVec);//把arrlist转换成坐标集合
- //重新定义中心点为原点
- //Vector3 centerPos = getPosCenter(vec);//获取中心点
- //int key = 0;
- //foreach (Vector3 item in vec)
- //{
- // item.setZero(centerPos);
- // vec[key] = item;
- // key++;
- //}
- return vec;//返回坐标集合
- }
+ ///
+ /// 输出日志回调函数
+ ///
+ /// 日志内容
+ public delegate void SomeCalculateWay(string str);
///
/// Arraylist 转 Vector3[] 坐标集
///
/// Arraylist 坐标集
/// Vector3[] 坐标集
- private static Vector3[] ArrToVec(ArrayList arr)
+ public static Vector3[] ArrToVec(ArrayList arr)
{
int cou = arr.Count;
Vector3[] re = new Vector3[cou];
@@ -428,16 +418,86 @@ namespace FlyBase
}
return re;
}
- //数组最大值 最小值
+ ///
+ /// 取数组最大 或者最小值
+ ///
+ /// 数组
+ /// true返回最大值 false返回最小值
+ /// 根据参数返回 最大或者最小值
private static double GetMaxOrMin(double[] arr, bool isMax = true)
{
- ArrayList list = new ArrayList(arr);
- list.Sort();
- if (isMax) return Convert.ToDouble(list[list.Count - 1]);
- else return Convert.ToDouble(list[0]);
-
+ Array.Sort(arr);//给数组arr排序
+ if (isMax)
+ return arr[arr.Length - 1];
+ else
+ return arr[0];
}
- //二维数组打成一维 去掉重复
+ ///
+ /// 取数组最大 或者最小值 的数组下标
+ ///
+ /// 数组
+ /// true返回最大值 false返回最小值
+ /// 数组下标
+ private static int GetIndexOfMaxOrMin(double[] arr, bool isMax = true)
+ {
+ int[] indexes = new int[arr.Length];
+ for (int i = 0; i < arr.Length; i++)
+ {
+ indexes[i] = i; // 保存每个元素的原始索引
+ }
+
+ Array.Sort(arr, indexes); // 按值排序同时更新索引数组
+
+ // 根据 isMax 参数返回相应的索引
+ return isMax ? indexes[arr.Length - 1] : indexes[0];
+ }
+ ///
+ /// 获取列表中最小值的随机下标
+ ///
+ /// 输入的列表
+ /// 最小值的随机下标
+ private static int GetRandomMinIndex(List list)
+ {
+ // 检查输入的列表是否为 null 或为空
+ if (list == null || list.Count == 0)
+ {
+ throw new ArgumentException("列表不能为 null 或为空");
+ }
+
+ int minValue = int.MaxValue; // 初始化为 int 类型的最大值
+ List minIndices = new List(); // 存储最小值的下标列表
+
+ for (int i = 0; i < list.Count; i++)
+ {
+ // 如果当前元素比最小值小,更新最小值和清空之前的下标列表
+ if (list[i] < minValue)
+ {
+ minValue = list[i];
+ minIndices.Clear(); // 清空之前的下标列表
+ minIndices.Add(i); // 添加当前下标
+ }
+ // 如果当前元素等于最小值,添加当前下标到列表
+ else if (list[i] == minValue)
+ {
+ minIndices.Add(i);
+ }
+ }
+
+ // 如果最小值下标列表为空,表示没有找到最小值
+ if (minIndices.Count == 0)
+ {
+ throw new InvalidOperationException("列表中没有找到最小值");
+ }
+
+ // 生成一个随机数,用于从最小值下标列表中随机选择一个下标
+ Random random = new Random();
+ return minIndices[random.Next(minIndices.Count)];
+ }
+ ///
+ /// 二维数组转一维数组 并去重
+ ///
+ /// 二维数组
+ /// 去重一维数组
private static ArrayList TwoArrToArr(ArrayList twoArr)
{
ArrayList arr = new ArrayList();
@@ -450,7 +510,11 @@ namespace FlyBase
}
return arr;
}
- //重写 泛值List int[]
+ ///
+ /// 二维数组转一维数组 并去重
+ ///
+ /// 二维数组
+ /// 去重一维数组
private static List TwoArrToArr(List twoArr)
{
List arr = new List();
@@ -464,6 +528,159 @@ namespace FlyBase
return arr;
}
///
+ /// 处理二维数组 把有关联的子数组合并 例如:[[0,2][0,3][3,4][5,6]] 结果[[0,2,3,4][5,6]]
+ ///
+ /// 需要处理的二维数组
+ /// 处理完成的数组
+ private static List> FindConnected(List arr)
+ {
+ Dictionary> graph = new Dictionary>();
+ Dictionary visited = new Dictionary();
+ List> result = new List>();
+ void DFS(int node, List connected)
+ {
+ visited[node] = true;
+ connected.Add(node);
+
+ foreach (var neighbor in graph[node])
+ {
+ if (!visited[neighbor])
+ {
+ DFS(neighbor, connected);
+ }
+ }
+ }
+ // 构建图
+ foreach (var edge in arr)
+ {
+ foreach (var node in edge)
+ {
+ if (!graph.ContainsKey(node))
+ {
+ graph[node] = new List();
+ visited[node] = false;
+ }
+ }
+ }
+ foreach (var edge in arr)
+ {
+ graph[edge[0]].Add(edge[1]);
+ graph[edge[1]].Add(edge[0]);
+ }
+ foreach (var node in graph.Keys)
+ {
+ if (!visited[node])
+ {
+ List connected = new List();
+ DFS(node, connected);
+ result.Add(connected);
+ }
+ }
+ return result;
+ }
+ ///
+ /// 获取一组序列的所有排列方式 ps:[0,1,2] 结果[[0, 1, 2],[0, 2, 1],[1, 0, 2],[1, 2, 0],[2, 0, 1],[2, 1, 0]]
+ ///
+ /// 一组序列
+ /// 所有序列的排列方式
+ public static List> Permutations(List array)
+ {
+ List> result = new List>();
+ GeneratePermutations(array, 0, array.Count - 1, result);
+ return result;
+ }
+ private static void GeneratePermutations(List array, int start, int end, List> result)
+ {
+ if (start == end)
+ {
+ result.Add(new List(array));
+ }
+ else
+ {
+ for (int i = start; i <= end; i++)
+ {
+ int temp = array[start];
+ array[start] = array[i];
+ array[i] = temp;
+ GeneratePermutations(array, start + 1, end, result);
+ temp = array[start];
+ array[start] = array[i];
+ array[i] = temp;
+ }
+ }
+ }
+ ///
+ /// 按照对应关系 生成新的b坐标集合
+ ///
+ /// a坐标集合
+ /// b坐标集合
+ /// a b集合的对应关系
+ /// 坐标集合
+ private static Vector3[] CreateNewBVecs(Vector3[] aVecs, Vector3[] bVecs, List match)
+ {
+ Dictionary indexMap = new Dictionary();
+ // 构建索引映射
+ foreach (var pair in match)
+ {
+ indexMap[pair[0]] = pair[1];
+ }
+ // 根据映射构建新的bb数组
+ Vector3[] new_bVecs = new Vector3[bVecs.Length];
+ foreach (var entry in indexMap)
+ {
+ int newIndex = entry.Value;
+ new_bVecs[newIndex] = bVecs[entry.Key];
+ }
+ return new_bVecs;
+ }
+ ///
+ /// 从一组向量集合中 不重复的随机选择4个向量为一组 最多100组 组合成二维数组 如:[[1,2,3,4][5,6,7,8]...]
+ ///
+ /// 坐标集和
+ /// re空数组则代表不够4个坐标
+ private static List RandomSel4Vec(Vector3[] vecs)
+ {
+ List result = new List();
+ int len = vecs.Length;
+ // 如果坐标数组少于4个,或者为空,则返回空列表
+ if (len < 4)
+ {
+ return result;
+ }
+ // 确定最大可选择的组数,最多为100组
+ int numGroups = Math.Min(len / 4, 100);
+ List flattenedList = vecs.ToList();
+ Random random = new Random();
+ // 遍历每一组
+ for (int i = 0; i < numGroups; i++)
+ {
+ List selectedGroup = new List();
+
+ // 随机选择4个不重复的坐标
+ for (int j = 0; j < 4; j++)
+ {
+ int index = random.Next(flattenedList.Count);
+ selectedGroup.Add(flattenedList[index]);
+ flattenedList.RemoveAt(index);
+ }
+
+ // 将选择的坐标组成的 List 转换为数组,并添加到结果中
+ result.Add(selectedGroup.ToArray());
+ }
+ return result;
+ }
+ ///
+ /// 设置中间航点
+ ///
+ /// 起点
+ /// 目标点
+ /// 比例
+ ///
+ private static Vector3 SetMiddleVec(Vector3 aVec, Vector3 bVec, double middlePos = 0.5)
+ {
+ return (bVec - aVec) * middlePos + aVec;
+ }
+ ///
/// 两点距离
///
/// 坐标1
@@ -471,14 +688,34 @@ namespace FlyBase
/// 两点之间距离
private static double GageLength(Vector3 v1, Vector3 v2)
{
- return Math.Sqrt(Math.Pow(v1.X - v2.X, 2) + Math.Pow(v1.Y - v2.Y, 2) + Math.Pow(v1.Z - v2.Z, 2));
+ return Math.Sqrt(GageLengthSquare(v1, v2));
}
- //点乘 用来求朝向 返回0到1之间
+ ///
+ /// 两点距离的平方
+ ///
+ /// 坐标1
+ /// 坐标2
+ /// 两点距离的平方
+ private static double GageLengthSquare(Vector3 v1, Vector3 v2)
+ {
+ return Math.Pow(v1.X - v2.X, 2) + Math.Pow(v1.Y - v2.Y, 2) + Math.Pow(v1.Z - v2.Z, 2);
+ }
+ ///
+ /// 点积
+ ///
+ /// 向量1
+ /// 向量2
+ /// 点积
private static double DotPro(Vector3 v1, Vector3 v2)
{
return v1.X * v2.X + v1.Y * v2.Y + v1.Z * v2.Z;
}
- //叉乘
+ ///
+ /// 叉积
+ ///
+ /// 向量1
+ /// 向量2
+ /// 两个向量叉积
private static Vector3 CrossPro(Vector3 v1, Vector3 v2)
{
double x = v1.Y * v2.Z - v1.Z * v2.Y;
@@ -487,10 +724,60 @@ namespace FlyBase
return new Vector3(x, y, z);
}
///
+ /// 检查4个点是否在一个平面上
+ ///
+ /// 点1
+ /// 点2
+ /// 点3
+ /// 点4
+ /// true在一个平面 false不在一个平面
+ public static bool IsVecsOnPlane(Vector3 vec1, Vector3 vec2, Vector3 vec3, Vector3 vec4)
+ {
+ // 计算两条边
+ Vector3 side1 = vec2 - vec1;
+ Vector3 side2 = vec3 - vec2;
+ // 计算法线向量
+ Vector3 normal = CrossPro(side1, side2);
+ // 计算第四个点到第一个点的向量
+ Vector3 toPoint4 = vec4 - vec1;
+ // 设置容差值,根据具体情况调整
+ float tolerance = 0.01f;
+ // 判断四个点是否在同一个平面上
+ return Math.Abs(DotPro(toPoint4, normal)) < tolerance;
+ }
+ ///
+ /// 判断4个点是否在同一条直线上
+ ///
+ /// 点1
+ /// 点2
+ /// 点3
+ /// 点4
+ /// true在一条直线上 false不在一条直线上
+ public static bool IsVecsOnLine(Vector3 vec1, Vector3 vec2, Vector3 vec3, Vector3 vec4)
+ {
+ // 计算相邻点之间的方向向量
+ Vector3 dir1 = new Vector3(vec2.X - vec1.X, vec2.Y - vec1.Y, vec2.Z - vec1.Z);
+ Vector3 dir2 = new Vector3(vec3.X - vec2.X, vec3.Y - vec2.Y, vec3.Z - vec2.Z);
+ Vector3 dir3 = new Vector3(vec4.X - vec3.X, vec4.Y - vec3.Y, vec4.Z - vec3.Z);
+
+ // 检查任意两个相邻方向向量的叉积是否为零
+ // 这是在三维空间中判断共线的条件
+ return CrossPro(dir1, dir2).IsZero() && CrossPro(dir2, dir3).IsZero();
+ }
+ ///
+ /// 辅助方法,用于检查向量是否为零向量
+ ///
+ /// 向量
+ ///
+ private static bool IsZero(this Vector3 vector)
+ {
+ return vector.X == 0 && vector.Y == 0 && vector.Z == 0;
+ }
+ ///
/// 坐标置换 向量乘以矩阵(i帽j帽k帽)得到置换后的向量坐标 ps:x指向i帽 y轴指向j帽 z轴指向k帽
///
/// 要变换的向量
- /// 矩阵标量 既i帽 j帽 k帽 三点的坐标组成的矩阵
+ /// 矩阵标量 既i帽 j帽 k帽 三点的坐标组成的矩阵 “可以想象成臂长为1的操作轴图标”
///
private static Vector3 MatrixMul(Vector3 vec, Vector3[] mat)
{
@@ -500,18 +787,25 @@ namespace FlyBase
re.Z = vec.X * mat[0].Z + vec.Y * mat[1].Z + vec.Z * mat[2].Z;
return re;
}
- //两条线段之间的最近距离
- private static bool IsEqual(double a, double b)
+ ///
+ /// 获取两条线段 的最近位置的距离和占比
+ ///
+ /// 线段1起始点
+ /// 线段1起终点
+ /// 线段2起始点
+ /// 线段2起终点
+ /// [在线段1占比,在线段2占比,最近距离]
+ public static double RecentlySquareOfLine(Vector3 a1, Vector3 a2, Vector3 b1, Vector3 b2)
{
- if (Math.Abs(a - b) < 1e-7)
+ bool IsEqual(double x, double y)
{
- return true;
+ if (Math.Abs(x - y) < 1e-7)
+ {
+ return true;
+ }
+ return false;
}
- return false;
- }
- private static double[] RecentlyOfLine(Vector3 a1, Vector3 a2, Vector3 b1, Vector3 b2)
- {
- if (a1 == a2) a2 += 1;
+ if (a1 == a2) a2 += 1;// 防止线段长度为0
if (b1 == b2) b2 += 1;
double ux = a2.X - a1.X;
double uy = a2.Y - a1.Y;
@@ -582,17 +876,41 @@ namespace FlyBase
double sc = 0.0;
double tc = 0.0;
if (IsEqual(sn, 0.0)) sc = 0.0;
- else sc = sn / sd;
+ else sc = sn / sd;//最近点在第一条线占比
if (IsEqual(tn, 0.0)) tc = 0.0;
- else tc = tn / td;
+ else tc = tn / td;//最近点在第二条线占比
double dx = wx + (sc * ux) - (tc * vx);
double dy = wy + (sc * uy) - (tc * vy);
double dz = wz + (sc * uz) - (tc * vz);
- double[] re = new double[3];
- re[0] = sc;//最近点在第一条线占比
- re[1] = tc;//最近点在第二条线占比
- re[2] = Math.Sqrt(dx * dx + dy * dy + dz * dz);//两线最近距离
- return re;
+ return dx * dx + dy * dy + dz * dz;//两线最近距离的平方
+ }
+ ///
+ /// 按比例在两条线段上截取对应点间的最小距离 平方
+ ///
+ /// 线段1起始点
+ /// 线段1起终点
+ /// 线段2起始点
+ /// 线段2起终点
+ /// 最小距离的平方值
+ public static double MinDistanceSquareOfLine(Vector3 a1, Vector3 a2, Vector3 b1, Vector3 b2)
+ {
+ //相对位置和相对速度
+ Vector3 d0 = b1 - a1;
+ Vector3 v_rel = (b2 - b1) - (a2 - a1);
+ //计算最小距离位置 占比
+ double vd = DotPro(v_rel, v_rel);
+ double proportion;//最近距离占比
+ if (vd != 0)
+ {
+ proportion = Math.Max(0, Math.Min(1, -DotPro(d0, v_rel) / vd));//max min函数把比例限制在0-1 保证比例在线段上
+ }
+ else
+ {
+ proportion = 0;
+ }
+ //计算最小距离平方
+ Vector3 d_min = d0 + v_rel * proportion;
+ return d_min.GetMagSquared();
}
///
/// 获取坐标集合的重心或中心
@@ -639,6 +957,50 @@ namespace FlyBase
}
}
///
+ /// 获取坐标集合的重心或中心
+ ///
+ /// 坐标集合
+ /// 默认返回为true重心 false则为中心
+ /// 重心或中心坐标
+ public static Vector3 GetPosCenter(List pos, bool isCentroid = true)
+ {
+ int cou = pos.Count;
+ if (isCentroid)//重心
+ {
+ double x = 0;
+ double y = 0;
+ double z = 0;
+ foreach (var item in pos)
+ {
+ x += item.X;
+ y += item.Y;
+ z += item.Z;
+ }
+ x = x / cou;
+ y = y / cou;
+ z = z / cou;
+ return new Vector3(x, y, z);
+ }
+ else
+ {
+ double[] x = new double[cou];
+ double[] y = new double[cou];
+ double[] z = new double[cou];
+ int key = 0;
+ foreach (var item in pos)
+ {
+ x[key] = item.X;
+ y[key] = item.Y;
+ z[key] = item.Z;
+ key++;
+ }
+ double xc = (GetMaxOrMin(x) + GetMaxOrMin(x, false)) * .5;
+ double yc = (GetMaxOrMin(y) + GetMaxOrMin(y, false)) * .5;
+ double zc = (GetMaxOrMin(z) + GetMaxOrMin(z, false)) * .5;
+ return new Vector3(xc, yc, zc);
+ }
+ }
+ ///
/// 获取坐标集合 的总宽度 高度 长度
///
/// 坐标集合
@@ -655,462 +1017,558 @@ namespace FlyBase
l.Add(item.Z);
}
double[] re = new double[3];
- re[0]=w.Max() - w.Min();
- re[1]=h.Max() - h.Min();
- re[2]=l.Max() - l.Min();
+ re[0] = w.Max() - w.Min();
+ re[1] = h.Max() - h.Min();
+ re[2] = l.Max() - l.Min();
return re;
}
- /*
- //从最外层AB规划路径
- private static void contactABOut(Vector3[] aPos, Vector3[] bPos,bool stressRefresh = true)
+ ///
+ /// 碰撞检测
+ ///
+ /// 始点坐标集合
+ /// 终点坐标集合
+ /// 航线最小间距平方值
+ /// 飞行过程中最小间距平方值
+ ///
+ public static List AirImitation(Vector3[] startPos, Vector3[] endPos, double lineDistanceSquare = 36100, double spaceBetweenSquare = 48400)
{
- if (!stressRefresh)//不刷新重心 初始化重心
+ List planesCollision = new List(); //所有碰撞的组
+ int planeCou = startPos.Length; //获取飞机总数
+ for (int a = 0; a < planeCou; a++)
{
- Vector3[] abPos = new Vector3[aPos.Length + bPos.Length];
- aPos.CopyTo(abPos, 0);
- bPos.CopyTo(abPos, aPos.Length);
- Vector3 centerPos=getPosCenter(abPos);//重心
- }
- while (aPos.Length != 0)
- {
- if (stressRefresh)//刷新重心
+ for (int b = 0; a + 1 + b < planeCou; b++)
{
- Vector3[] abPos = new Vector3[aPos.Length + bPos.Length];
- aPos.CopyTo(abPos, 0);
- bPos.CopyTo(abPos, aPos.Length);
- Vector3 centerPos = getPosCenter(abPos);//重心
- }
-
- }
- }
- */
- //输出日志回调函数
- public delegate void SomeCalculateWay(string str);
- //碰撞检测
- public static List AirImitation(Vector3[] startPos, Vector3[] endPos, double lineDistance = 180, double spaceBetween = 900, int checkFps = 10)
- {
- int cou = startPos.Length;//飞机总数
- //获取所有飞行时间 和航线距离
- double[] planesLen = new double[cou];//记录所有航线距离
- double[] planesFlyTime = new double[cou];//记录所有飞行时间
- for (int i = 0; i < cou; i++)
- {
- double len = GageLength(startPos[i], endPos[i]);//距离
- planesLen[i] = len;
- double flyTime = len / 300;//时间
- planesFlyTime[i] = flyTime;
- }
- //选出航线有交叉的飞机 用于模拟飞行碰撞检测
- List needCheck = new List();//需要检查的飞机 二维数组 记录交叉组
- List distances = new List();//记录所有需要检查飞机 航线的最短距离
- for (int i = 0; i < cou; i++)
- {
- for (int x = 0; x < cou; x++)
- {
- if (i + 1 + x < cou)
+ //判断两条轨迹 之间的最小距离
+ double distanceSquare = RecentlySquareOfLine(startPos[a], endPos[a], startPos[a + 1 + b], endPos[a + 1 + b]);
+ if (distanceSquare < lineDistanceSquare)
{
- double distance = RecentlyOfLine(startPos[i], endPos[i], startPos[i + 1 + x], endPos[i + 1 + x])[2];//航线距离
- if (distance < lineDistance)
+ //判断飞机距离是否过近
+ double planeLenSquare = MinDistanceSquareOfLine(startPos[a], endPos[a], startPos[a + 1 + b], endPos[a + 1 + b]);
+ if (planeLenSquare < spaceBetweenSquare)
{
- int[] z = new int[] { i, i + 1 + x };
- needCheck.Add(z);
- distances.Add(distance);
+ planesCollision.Add(new int[] { a, a + 1 + b });
}
}
- else break;
}
}
- //碰撞检测
- List planesCollision = new List();//记录碰撞组
- for (int i = 0; i < needCheck.Count; i++)
- {
- double zongTime;
- int frist = (needCheck[i])[0];//第一架
- int second = (needCheck[i])[1];//第二架
- Vector3 fristFormerly = endPos[frist];//记第一架 终点原位
- Vector3 secondFormerly = endPos[second];//记第二架 终点原位
- //获取对比飞机 飞行时间较长的时间
- if (planesFlyTime[frist] >= planesFlyTime[second]) zongTime = planesFlyTime[frist] + 1;//最长飞行时间 多加1秒放bug
- else zongTime = planesFlyTime[second] + 1;//最长飞行时间 多加1秒放bug
- Convert.ToInt32(zongTime);
- //以帧为单位计算 检测对比飞机之间距离
- for (int currentTime = 0; currentTime < zongTime * checkFps; currentTime++)
- {
- endPos[frist].SetZero(startPos[frist]);//归零
- endPos[frist].Normalize(300 / checkFps * currentTime);//当前时间飞行 标准化长度 坐标
- if (endPos[frist].GetMag() >= planesLen[frist]) endPos[frist] = fristFormerly;//溢出距离 当前坐标定义为终点位置
- else endPos[frist].SetFormerly(startPos[frist]);//归位 当前时间飞机坐标
-
- endPos[second].SetZero(startPos[second]);//归零
- endPos[second].Normalize(300 / checkFps * currentTime);//当前时间飞行 标准化长度 坐标
- if (endPos[second].GetMag() >= planesLen[second]) endPos[second] = secondFormerly;//溢出距离 当前坐标定义为终点位置
- else endPos[second].SetFormerly(startPos[second]);//归位 当前时间飞机坐标
-
- //判断距离 碰撞记录id
- if (GageLength(endPos[frist], endPos[second]) < spaceBetween + 300 * ((double)distances[i] / lineDistance))//间距小于 基础间距+300*(航线实际距离/航线检测最小距离) 既:例基础间距+航线距离的反比
- {
- endPos[frist] = fristFormerly;//第一架 终点回归原位
- endPos[second] = secondFormerly;//第二架 终点回归原位
- int[] z = new int[] { frist, second };
- planesCollision.Add(z);
- break;
- }
- endPos[frist] = fristFormerly;//第一架 终点回归原位
- endPos[second] = secondFormerly;//第二架 终点回归原位
- }
- }
- return planesCollision;//返回二维数组 飞机ID从0开始
+ return planesCollision;
}
- //单机碰撞检测
- public static bool OnlyImitation(int onlyPlaneId, Vector3[] startPos, Vector3[] endPos, double lineDistance = 180, double spaceBetween = 1200, int checkFps = 10)//飞机id从0开始
+ ///
+ /// 碰撞检测
+ ///
+ /// 始点坐标集合
+ /// 终点坐标集合
+ /// 航线最小间距平方值
+ /// 飞行过程中最小间距平方值
+ ///
+ public static List AirImitation(List startPos, List endPos, double lineDistanceSquare = 36100, double spaceBetweenSquare = 48400)
+ {
+ List planesCollision = new List(); //所有碰撞的组
+ int planeCou = startPos.Count; //获取飞机总数
+ for (int a = 0; a < planeCou; a++)
+ {
+ for (int b = 0; a + 1 + b < planeCou; b++)
+ {
+ //判断两条轨迹 之间的最小距离
+ double distanceSquare = RecentlySquareOfLine(startPos[a], endPos[a], startPos[a + 1 + b], endPos[a + 1 + b]);
+ if (distanceSquare < lineDistanceSquare)
+ {
+ //判断飞机距离是否过近
+ double planeLenSquare = MinDistanceSquareOfLine(startPos[a], endPos[a], startPos[a + 1 + b], endPos[a + 1 + b]);
+ if (planeLenSquare < spaceBetweenSquare)
+ {
+ planesCollision.Add(new int[] { a, a + 1 + b });
+ }
+ }
+ }
+ }
+ return planesCollision;
+ }
+ ///
+ /// 单机碰撞检测
+ ///
+ /// 飞机的id PS:id从0开始
+ /// 飞机起始坐标集合
+ /// 飞机终点坐标集合
+ /// 航线小距离的平方对比值
+ /// 飞行过程中最小间距的平方对比值
+ /// true:有碰撞 false:无碰撞
+ public static bool OnlyImitation(int onlyPlaneId, Vector3[] startPos, Vector3[] endPos, double lineDistanceSquare = 32400, double spaceBetweenSquare = 90000)
{
- //指定飞机 起始坐标 终点坐标 飞行时间
- Vector3 onlyStartVec = startPos[onlyPlaneId];
- Vector3 onlyEndVec = endPos[onlyPlaneId];
- double onlyFlyTime = GageLength(onlyStartVec, onlyEndVec) / 300;
//选出与指定飞机 航线有交叉的飞机 用于模拟飞行碰撞检测
for (int contrastId = 0; contrastId < startPos.Length; contrastId++)
{
if (onlyPlaneId == contrastId) continue;//不和自己比较
- Vector3 StartVec = startPos[contrastId];//对比飞机起始坐标
- Vector3 EndVec = endPos[contrastId];//对比飞机结束坐标
// 判断两条轨迹 之间的最小距离
- double distance = RecentlyOfLine(onlyStartVec, onlyEndVec, StartVec, EndVec)[2];//航线最小距离
- if (distance < lineDistance)
+ double distanceSquare = RecentlySquareOfLine(startPos[onlyPlaneId], endPos[onlyPlaneId], startPos[contrastId], endPos[contrastId]);//航线最小距离
+ if (distanceSquare < lineDistanceSquare)
{
- double flyTime = GageLength(EndVec, StartVec) / 300;//获取飞行总时间
- //指定飞机 和 当前比较飞机 以飞行时间长得为总时间
- int zongFlyTime;//声明 以航线较长的飞行时间 为总时长
- if (onlyFlyTime >= flyTime) zongFlyTime = (int)onlyFlyTime + 1;//总时间延长一到两秒
- else zongFlyTime = (int)flyTime + 1;//总时间延长一到两秒
- //碰撞检测
- for (int currentTime = 0; currentTime < zongFlyTime * checkFps; currentTime++)
+ double minDistanceSquare = MinDistanceSquareOfLine(startPos[onlyPlaneId], endPos[onlyPlaneId], startPos[contrastId], endPos[contrastId]);//按比例飞行最小间距
+ if (minDistanceSquare < spaceBetweenSquare)
{
- //飞机当前坐标
- Vector3 onlyCurrentVec = onlyEndVec.SetZeroEd(onlyStartVec);//归零的 当前坐标
- onlyCurrentVec.Normalize(300 / checkFps * currentTime);//当前时间飞行 标准化长度 坐标
- if (onlyCurrentVec.GetMag() >= GageLength(onlyEndVec, onlyStartVec)) onlyCurrentVec = onlyEndVec;//溢出距离 当前坐标定义为终点位置
- else onlyCurrentVec.SetFormerly(onlyStartVec);//归位 当前时间飞机坐标
-
- //要进行比较飞机 当前坐标
- Vector3 currentVec = EndVec.SetZeroEd(StartVec);//归零的 当前坐标
- currentVec.Normalize(300 / checkFps * currentTime);//当前时间飞行 标准化长度 坐标
- if (currentVec.GetMag() >= GageLength(EndVec, StartVec)) currentVec = EndVec;//溢出距离 当前坐标定义为终点位置
- else currentVec.SetFormerly(StartVec);//归位 当前时间飞机坐标
-
- double planeLen = GageLength(onlyCurrentVec, currentVec);//获取检测飞机s 当前间距
- //间距小于 基础间距+800*(航线实际距离/航线检测最小距离) 既:例基础间距+航线距离的反比
- if (planeLen < spaceBetween + 300 * (distance / lineDistance))
- {
- return true;//返回有碰撞
- }
+ return true;//返回有碰撞
}
}
}
return false;//返回没有碰撞;
}
- //智能挫层
- public static ArrayList CollisionLayer(Vector3[] startPos, Vector3[] endPos, string axes = "y")
+ ///
+ /// 单机碰撞检测
+ ///
+ /// 飞机的id PS:id从0开始
+ /// 飞机起始坐标集合
+ /// 飞机终点坐标集合
+ /// 航线小距离的平方对比值
+ /// 飞行过程中最小间距的平方对比值
+ /// true:有碰撞 false:无碰撞
+ public static bool OnlyImitation(int onlyPlaneId, List startPos, List endPos, double lineDistanceSquare = 32400, double spaceBetweenSquare = 90000)
{
- //获取所有碰撞飞机id
- List planesCollisionInt = new List();//声明碰撞id组
- int key = 0;
- foreach (var item in startPos)//遍历所有飞机 单体检测碰撞
+ //选出与指定飞机 航线有交叉的飞机 用于模拟飞行碰撞检测
+ for (int contrastId = 0; contrastId < startPos.Count; contrastId++)
{
- if (OnlyImitation(key, startPos, endPos)) planesCollisionInt.Add(key);//如果碰撞 添加到碰撞id组
- key++;
- }
- //记录第一图案原位
- double defaultPos = startPos[0].Y;
- //有碰撞飞机先拉开
- int k = 0;
- foreach (int i in planesCollisionInt)
- {
- startPos[i].Y = startPos[i].Y + 9400 + k * 300;
- k++;
- }
- //中间航点挫层
- foreach (int i in planesCollisionInt)
- {
- int shiftCou = 0;//记录循环次数
- while (true)
+ if (onlyPlaneId == contrastId) continue;//不和自己比较
+ // 判断两条轨迹 之间的最小距离
+ double distanceSquare = RecentlySquareOfLine(startPos[onlyPlaneId], endPos[onlyPlaneId], startPos[contrastId], endPos[contrastId]);//航线最小距离
+ if (distanceSquare < lineDistanceSquare)
{
+ double minDistanceSquare = MinDistanceSquareOfLine(startPos[onlyPlaneId], endPos[onlyPlaneId], startPos[contrastId], endPos[contrastId]);//按比例飞行最小间距
+ if (minDistanceSquare < spaceBetweenSquare)
+ {
+ return true;//返回有碰撞
+ }
+ }
+ }
+ return false;//返回没有碰撞;
+ }
+ ///
+ /// 智能路径 规则:找ab组共同最外圈的点 然后对应找a或b里面最近点 为一组匹配 最后进行碰撞交叉互换
+ ///
+ /// 起始点坐标组
+ /// 目标点坐标组
+ /// 交换次数
+ ///
+ public static Vector3[] ContactABOut(Vector3[] aVecs, Vector3[] bVecs, int swapCount = 5)
+ {
+ int planeCou = aVecs.Length; // 飞机总数
+ List match = new List(); // ab对应关系
+ //记录a b集合索引
+ List aIndex = new List();
+ List bIndex = new List();
+ for (int k = 0; k < planeCou; k++)
+ {
+ aIndex.Add(k);
+ bIndex.Add(k);
+ }
+ // 遍历找出 AB集合对应关系
+ for (int k = 0; k < planeCou; k++)
+ {
+ // 遍历每次刷新 剩下为未匹配总数
+ int remainCou = aIndex.Count;
+ // 遍历每次刷新 重心
+ List allVecs = new List();
+ for (int i = 0; i < remainCou; i++)
+ {
+ allVecs.Add(aVecs[aIndex[i]]);
+ allVecs.Add(bVecs[bIndex[i]]);
+ }
+ Vector3 centerVec = GetPosCenter(allVecs);//重心点
+ // 遍历所有ab点距离重心点的距离
+ double[] aLens = new double[remainCou];
+ 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);
+ }
+ // 找出ab集合最外层坐标的下标 即离重心点最远的点
+ int aMaxIndex = GetIndexOfMaxOrMin(aLens); // a集合到重心点最长的距离 数组的下标
+ int bMaxIndex = GetIndexOfMaxOrMin(bLens); // b集合到重心点最长的距离 数组的下标
+ if (aLens[aMaxIndex] > bLens[bMaxIndex])//找出 最外层如果为A集合点 对应B集合最近点 的下标
+ {
+ //MessageBox.Show(aIndex[aMaxIndex].ToString());
+ double[] outAtoBLen = new double[remainCou];//最外层A点到 B集合所有点的距离
+ for (int i = 0; i < remainCou; i++)
+ {
+ outAtoBLen[i] = GageLengthSquare(aVecs[aIndex[aMaxIndex]], bVecs[bIndex[i]]);
+ }
+ int bMinIndex = GetIndexOfMaxOrMin(outAtoBLen, false);// 最短距离
+ match.Add(new int[] { aIndex[aMaxIndex], bIndex[bMinIndex] });// 映射到配对
+ aIndex.RemoveAt(aMaxIndex); // 删除已经配对的a集合 ID
+ bIndex.RemoveAt(bMinIndex); // 删除已经配对的b集合 ID
+ }
+ else//找出 最外层如果为B集合点 对应A集合最近点 的下标
+ {
+ double[] outBtoALen = new double[remainCou];//最外层B点到 A集合所有点的距离
+ for (int i = 0; i < remainCou; i++)
+ {
+ outBtoALen[i] = GageLengthSquare(aVecs[aIndex[i]], bVecs[bIndex[bMaxIndex]]);
+ }
+ int aMinIndex = GetIndexOfMaxOrMin(outBtoALen, false);// 最短距离
+ match.Add(new int[] { aIndex[aMinIndex], bIndex[bMaxIndex] });// 映射到配对
+ aIndex.RemoveAt(aMinIndex); // 删除已经配对的a集合 ID
+ bIndex.RemoveAt(bMaxIndex); // 删除已经配对的b集合 ID
+ }
+ }
+ Vector3[] new_bVecs = CreateNewBVecs(aVecs, bVecs, match);// 按照映射 获取a 对应的 新的b集合
+ return new_bVecs;
+
+ //交叉 交换
+ for (int i = 0; i < swapCount; i++)
+ {
+ List planesCollision = AirImitation(aVecs, new_bVecs);// 获取碰撞组
+ List> formatCollision = FindConnected(planesCollision);// 格式化碰撞检测组 例如:[[0,2][0,3][3,4][5,6]] 结果[[0,2,3,4][5,6]]
+ // 遍历所有交叉组 分组做交换
+ foreach (List swap_indices in formatCollision)
+ {
+ if (swap_indices.Count <= 6) // 只尝试5组交叉碰撞以下的航线互换
+ {
+ //交叉 生成所有排列
+ List> all_permutations = Permutations(swap_indices);
+ //删掉第一个 既原始排列
+ all_permutations.RemoveAt(0);
+ // 按所有的排列 互换航线 并检测出最佳的对应目标点
+ List tempLen = new List(); //记录所有排列的 的碰撞次数
+ List tempNew_bVecsS = new List();//记录所有排列交换之后的目标坐标集
+ foreach (List indices in all_permutations)
+ {
+ Vector3[] current_array = new_bVecs.ToArray();//复制一个new_bVecs 副本
+ for (int k = 0; k < indices.Count - 1; k++)
+ {
+ int index1 = indices[k];
+ int index2 = indices[k + 1];
+ // 交换元素
+ Vector3 temp = current_array[index1];
+ current_array[index1] = current_array[index2];
+ current_array[index2] = temp;
+ }
+ tempLen.Add(AirImitation(aVecs, current_array).Count);// 迭代 记录所有排列的碰撞次数
+ tempNew_bVecsS.Add(current_array); //迭代 记录所有排列交换之后的目标坐标集
+ }
+ new_bVecs = tempNew_bVecsS[GetRandomMinIndex(tempLen)];
+ }
+ }
+ }
+ return new_bVecs;
+ }
+ ///
+ /// 智能挫层
+ ///
+ /// 起始坐标集合
+ /// 终点做标集合
+ /// 挫层层高
+ /// 返回一个二维向量坐标集合 middle[0]是第一个中间航点 middle[1]是第二个中间航点 返回空数组则代表两个图形不在一个平面上或者不够4个点
+ public static List CollisionLayer(Vector3[] startPos, Vector3[] endPos, double layHight = 220)
+ {
+ List re = new List();
+ //获取飞机总数
+ int planeCou = startPos.Length;
+ //检测两个图形是否在一个平面上
+ Vector3[] allPos = startPos.Concat(endPos).ToArray();//合并两个集合
+ List ppppVecArr = RandomSel4Vec(allPos);//随机选择
+ if (ppppVecArr.Count == 0)//两个图形不够四个点 返回 空数组
+ {
+ return re;
+ }
+ // 使用 foreach 遍历 List 中的元素
+ foreach (Vector3[] pppVec in ppppVecArr)
+ {
+ if (!(IsVecsOnPlane(pppVec[0], pppVec[1], pppVec[2], pppVec[3])))
+ {
+ return re;//两个图形不在一个平面上 返回 空数组
+ }
+
+ }
+ //遍历选出4个不共线的点 ps:方便后续叉积算法线标量
+ bool isVecsOnLine = false; Vector3 vec0 = new Vector3(0, 0, 0); Vector3 vec1 = new Vector3(0, 0, 0); Vector3 vec2 = new Vector3(0, 0, 0); Vector3 vec3 = new Vector3(0, 0, 0);
+ for (int i = 0; i < planeCou; i++) //遍历所有点 找出不在一条直线上的四个点
+ {
+ vec0 = startPos[i]; vec1 = endPos[planeCou - i - 1]; vec2 = startPos[planeCou - i - 1]; vec3 = endPos[i];
+ isVecsOnLine = IsVecsOnLine(vec0, vec1, vec2, vec3);
+ if (isVecsOnLine)
+ {
+ break;
+ }
+ }
+ if (isVecsOnLine)
+ {
+ return re;//两个图案的所有点都在一条直线上 返回 空数组
+ }
+ //检查完毕后
+ //计算法线向量
+ Vector3 side1 = vec0 - vec1;
+ Vector3 side2 = vec2 - vec3;
+ Vector3 normal = CrossPro(side1, side2);
+ Vector3 normalScalar = normal.NormalizEd();//法线标量
+ //开始挫层
+ for (int i = 0; i < planeCou; i++)
+ {
+ int shiftCou = 1; //记录循环次数 即层数
+ Vector3 aOrigin = startPos[i]; //原点位置
+ Vector3 bOrigin = endPos[i]; //原点位置
+ while (OnlyImitation(i, startPos, endPos))
+ {
+ Vector3 shiftVec = normalScalar * ((shiftCou + 1) / 2 * layHight);
if (shiftCou % 2 == 1)
{
- startPos[i].Y = defaultPos + (shiftCou + 1) / 2 * 350;
- endPos[i].Y = defaultPos + (shiftCou + 1) / 2 * 350;
+ startPos[i] = aOrigin + shiftVec;
+ endPos[i] = bOrigin + shiftVec;
}
else
{
- startPos[i].Y = defaultPos + shiftCou / 2 * -350;
- endPos[i].Y = defaultPos + shiftCou / 2 * -350;
+ startPos[i] = aOrigin - shiftVec;
+ endPos[i] = bOrigin - shiftVec;
}
- if (!(OnlyImitation(i, startPos, endPos))) break;//如果 不碰撞跳出
- shiftCou++;
+ shiftCou += 1;
}
}
- ArrayList middle = new ArrayList();
- middle.Add(startPos);
- middle.Add(endPos);
- return middle;//返回一个二维向量数组 middle[0]是第一个中间航点 middle[1]是第二个中间航点
- }
- //添加中间航点 群组
- private static Vector3[] SetMiddleCurvedValue(Vector3[] startPos, Vector3[] endPos, double middlePos = 0.5, double scale = 1)
- {
- int cou = startPos.Length;//飞机总数
- Vector3[] mps = new Vector3[cou];
- //算中间航点
- for (int i = 0; i < cou; i++)
- {
- Vector3 ap = startPos[i];
- Vector3 bp = endPos[i];
- mps[i] = (bp - ap) * middlePos + ap;
- }
- Vector3 centerPos = GetPosCenter(mps);//计算所有中间航点的重心点
- //中间航点缩放
- for (int i = 0; i < cou; i++)
- {
- mps[i] = (mps[i] - centerPos) * scale + centerPos + .1;
- }
- return mps;
- }
- //添加中间航点 单体
- private static Vector3 SetOddMiddleCurvedValue(Vector3 startPos, Vector3 endPos, double middlePos = 0.5)
- {
- //算中间航点
- Vector3 mp = (endPos - startPos) * middlePos + startPos + .1;
- return mp;
- }
- //3D绕行与让行 ps:起点s 中点s 终点s 需要检查的ID组 绕行比例 每个比例的绕行次数 绕行的法线偏移距离
- private static Vector3[] ABypassB(Vector3[] startPos, Vector3[] middlePos, Vector3[] endPos, List check, double[] mRate, int loopIndex = 800, double offsetDistance = 60)//法线螺旋线绕行
- {
- Console.WriteLine("check:{0}", check.Count);
- bool pa;
- //设置绕行
- foreach (int id in check)
- {
- pa = false;
- Vector3 initialPos = middlePos[id];//记录初始位置 如果绕行不成功 还原位置
- for (int k = 0; k < mRate.Length; k++)
- {
- //初始化位置
- middlePos[id] = SetOddMiddleCurvedValue(startPos[id], endPos[id], mRate[k]);
- //碰撞绕行
- for (int i = 0; i < loopIndex; i++)
- {
- if (i != 0)//第一次保证原位置 ps:先不移动位置 检测一次 移动其他飞机之后 可能让本架飞机不碰撞
- {
- //获取法线向量
- Vector3 a = startPos[id];
- Vector3 b = endPos[id];
- Vector3 c = middlePos[id];
- Vector3 mp = FlyVecFun.CrossPro(a - c, b - c);//乘差算 坐标原点上面的法线 方向向量
- if (k % 2 == 0) mp.Normalize(offsetDistance);//正螺旋
- else mp.Normalize(offsetDistance * -1);//逆螺旋
- middlePos[id] = mp + c;
- }
- //碰撞检测
- if (OnlyImitation(id, startPos, middlePos)) continue;//前半段检测
- if (OnlyImitation(id, middlePos, endPos)) continue;//后半段检测
- pa = true;
- break;
- }
- if (pa) break;
- }
- if (!pa) middlePos[id] = initialPos;//让行不成功 位置还原
- }
- return middlePos;
- }
- private static List ThreeStageABypassB(Vector3[] startPos, Vector3[] fMiddlePos, Vector3[] middlePos, Vector3[] bMiddlePos, Vector3[] endPos, List check, double[] mRate)//三段绕
- {
- //初始化
- double[] fmRate = { 0 };
- double[] bmRate = { 1 };
- //二段绕行
- foreach (int id in check)
- {
- bool pa = false;
- Vector3 initialPos = middlePos[id];//记录初始位置 如果绕行不成功 还原位置
- for (int k = 0; k < mRate.Length; k++)
- {
-
- //初始化位置
- middlePos[id] = SetOddMiddleCurvedValue(startPos[id], endPos[id], mRate[k]);
- //二段碰撞绕行
- for (int i = 0; i < 800; i++)
- {
- if (i != 0)//第一次保证原位置 ps:先不移动位置 检测一次 移动其他飞机之后 可能让本架飞机不碰撞
- {
- //获取法线向量
- Vector3 a = startPos[id];
- Vector3 b = endPos[id];
- Vector3 c = middlePos[id];
- Vector3 mp = FlyVecFun.CrossPro(a - c, b - c);//乘差算 坐标原点上面的法线 方向
- mp.Normalize(60);
- middlePos[id] = mp + c;
- }
- //绕一段 和 三段
- Vector3[] tempFMiddlePos;//临时存放 一段
- Vector3[] tempBMiddlePos;//临时存放 三段
- List xId = new List();//临时存放当前id 用于绕行方法
- xId.Add(id);
- if (OnlyImitation(id, startPos, middlePos) || OnlyImitation(id, middlePos, endPos))//因为二段改变位置 检测直接二段绕行 是否通过
- {
- tempFMiddlePos = FlyVecFun.ABypassB(startPos, fMiddlePos, middlePos, xId, fmRate, 45, 90);//一段绕行
- if (OnlyImitation(id, startPos, tempFMiddlePos)) continue;//检测一段 前 重新循环二段
- else if (OnlyImitation(id, tempFMiddlePos, middlePos)) continue;//检测一段 后 重新循环二段
-
- tempBMiddlePos = FlyVecFun.ABypassB(middlePos, bMiddlePos, endPos, xId, bmRate, 45, 90);//三段绕行
- if (OnlyImitation(id, startPos, tempBMiddlePos)) continue;//检测三段 前 重新循环二段
- else if (OnlyImitation(id, fMiddlePos, middlePos)) continue;//检测三段 后 重新循环二段
-
- fMiddlePos = tempFMiddlePos;//如果通过 更新一段坐标
- bMiddlePos = tempBMiddlePos;//如果通过 更新三段坐标
- }
- pa = true;
- break;//跳出
- }
- if (pa) break;
- }
- if (!pa) middlePos[id] = initialPos;//绕行不成功 位置还原
- }
- List re = new List();
- re.Add(fMiddlePos);
- re.Add(middlePos);
- re.Add(bMiddlePos);
+ re.Add(startPos);
+ re.Add(endPos);
return re;
}
- private static List ABNeedCheck(Vector3[] startPos, Vector3[] middlePos, Vector3[] endPos)//前航点到中间航点 中间航点到终点 所有碰撞飞机id
+ ///
+ /// 路径绕行
+ ///
+ /// 起始坐标集合
+ /// 终点做标集合
+ /// 返回一个二维数组 长度为1即1个中间航点 长度为3即前中后三个中间航点
+ public static List> ABypassB(Vector3[] aVecs, Vector3[] bVecs)
{
- List re = new List();
- //获取从起点到中点再到结束点 所有碰撞飞机
- int key = 0;
- foreach (var item in startPos)
+ List> re = new List>();
+ int planeCou = aVecs.Length;
+ //第一次绕行
+ //起始坐标组重心点 与 目标坐标组重心点
+ Vector3 aCenterPoint = GetPosCenter(aVecs);
+ Vector3 bCenterPoint = GetPosCenter(bVecs);
+ //记录所有航线中心距 ps:起点离起点组中心点距离 + 目标点离目标点组中心点距离
+ double[] centerDistanceS = new double[planeCou];
+ for (int i = 0; i < planeCou; i++)
{
- if (OnlyImitation(key, startPos, middlePos) || OnlyImitation(key, middlePos, endPos)) re.Add(key);//记录 起点到中点 或者 中点到终点有碰撞的飞机
- key++;
+ centerDistanceS[i] = GageLengthSquare(aVecs[i], aCenterPoint) + GageLengthSquare(bVecs[i], bCenterPoint);
}
+ //记录从中心开始排序
+ int[] sortedIndices = Enumerable.Range(0, centerDistanceS.Length).ToArray();
+ Array.Sort(sortedIndices, (x, y) => centerDistanceS[x].CompareTo(centerDistanceS[y]));// 对索引数组按原始数组的值进行排序
+ //从中心航线 逐条绕行 ps:映射从中心内部到此到外部顺序
+ List tempAVecs = new List(); // 逐条起点坐标组
+ List tempBVecs = new List(); // 逐条目标点坐标组
+ List middleVecs = new List(); //中心航点坐标组
+ List firstCollisionGroup = new List(); //有碰撞飞机列表(第一次绕行)
+ for (int i = 0; i < planeCou; i++)
+ {
+ bool isPassMark = false;//初始标记
+ int index = sortedIndices[i];//从内到外排序的索引
+ tempAVecs.Add(aVecs[index]);
+ tempBVecs.Add(bVecs[index]);
+ if (i == 0) //如果是第一条航线 直接添加中间航点
+ {
+ middleVecs.Add(SetMiddleVec(aVecs[index], bVecs[index])); //添加中间航点
+ }
+ else //从第二条开始绕
+ {
+ middleVecs.Add(SetMiddleVec(aVecs[index], bVecs[index])); // 添加默认中间航点
+ // 首次默认中间航点检测
+ if (!(OnlyImitation(i, tempAVecs, middleVecs))) //前半段碰 碰撞检测
+ {
+ if (!(OnlyImitation(i, middleVecs, tempBVecs))) //后半段碰 碰撞检测
+ {
+ isPassMark = true; //中间航点
+ continue; //不撞则跳出 进行下一航线的绕行
+ }
+ else
+ {
+ middleVecs.RemoveAt(i); //碰撞检测未通过删除临时中间航点
+ }
+ }
+ else
+ {
+ middleVecs.RemoveAt(i); //碰撞检测未通过删除临时中间航点
+ }
+ // 绕行列表遍历 检测
+ List ringVecs = GetRingVec(aVecs[index], bVecs[index], 0.5); //所有可绕行的中间航点集合
+ foreach (Vector3 v in ringVecs)
+ {
+ middleVecs.Add(v);
+ //检测
+ if (!(OnlyImitation(i, tempAVecs, middleVecs))) //前半段碰 碰撞检测
+ {
+ if (!(OnlyImitation(i, middleVecs, tempBVecs))) //后半段碰 碰撞检测
+ {
+ isPassMark = true; //中间航点 碰撞检测通过标记
+ break; //不撞则跳出 进行下一航线的绕行
+ }
+ else
+ {
+ middleVecs.RemoveAt(i); //碰撞检测未通过删除临时中间航点
+ }
+ }
+ else
+ {
+ middleVecs.RemoveAt(i); //碰撞检测未通过删除临时中间航点
+ }
+ }
+ }
+ if (!(isPassMark)) // 如果绕行失败 添加一个默认中间航点
+ {
+ middleVecs.Add(SetMiddleVec(aVecs[index], bVecs[index]));
+ firstCollisionGroup.Add(index);
+ }
+ }
+ //中间航点坐标集 按飞机id顺序重新映射 ps:恢复原id映射
+ middleVecs = sortedIndices.Select(index => middleVecs[index]).ToList();
+ //没有碰撞 返回一个中间航点 并返回
+ if (firstCollisionGroup.Count == 0)
+ {
+ re.Add(middleVecs);
+ return re;
+ }
+
+ //第二次绕行 ps:有碰撞进行第二次 前后再各加以航点 嵌套迭代
+ List firstMiddleVecs = new List(); //前中间航点
+ List secondMiddleVecs = new List(); //后中间航点
+ List secondCollisionGroup = new List(); //最终有碰撞飞机列表
+ for (int i = 0; i < planeCou; i++)
+ {
+ firstMiddleVecs.Add(SetMiddleVec(aVecs[i], middleVecs[i], 0));
+ secondMiddleVecs.Add(SetMiddleVec(middleVecs[i], bVecs[i], 1));
+ }
+ foreach (int index in firstCollisionGroup)
+ {
+ bool isPassMark = false;
+ // 正中 绕行列表
+ List ringVecs = GetRingVec(aVecs[index], bVecs[index], 0.5); //所有可绕行的中间航点集合
+ foreach (Vector3 r in ringVecs)
+ {
+ middleVecs[index] = r; //中点逐点
+ List firstRingVecs = GetRingVec(aVecs[index], middleVecs[index], 0, 220, 6); //所有可绕行的 前中间航点集合
+ foreach (Vector3 fr in firstRingVecs)
+ {
+ firstMiddleVecs[index] = fr; //前中点逐点
+ List secondRingVecs = GetRingVec(middleVecs[index], bVecs[index], 1, 220, 6); //所有可绕行的 后中间航点集合
+ foreach (Vector3 sr in secondRingVecs)
+ {
+ secondMiddleVecs[index] = sr; //后中点逐点
+ // 检测
+ if (!(OnlyImitation(index, aVecs, firstMiddleVecs))){
+ }
+ //if not(self.onlyImitation(v, aVecs, firstMiddleVecs)): #前半段碰 碰撞检测
+ // if not(self.onlyImitation(v, firstMiddleVecs, middleVecs)):#后半段碰 碰撞检测
+ // if not(self.onlyImitation(v, middleVecs, secondMiddleVecs)): #前半段碰 碰撞检测
+ // if not(self.onlyImitation(v, secondMiddleVecs, bVecs)):#后半段碰 碰撞检测
+ // isPassMark = True #碰撞检测通过标记
+ // break #不撞则跳出 进行下一航线的绕行
+ }
+ }
+ }
+ }
+
return re;
}
- public static List ExeABypassB(Vector3[] startPos, Vector3[] endPos, out bool isSuccess, SomeCalculateWay strPrint)//绕行获取中间航点
+ ///
+ /// 在圆圈上 用固定弦长手拉手 分割点
+ ///
+ /// 大圆半径
+ /// 固定弦长 ps:这个值决定绕行点一圈的密集成都值越小越密集
+ ///
+ public static List GetVecsOnCircle(double radius, double chordLength = 220)
{
- isSuccess = false;
- List middlePosS = new List();//声明返回坐标集合 可能是1 到 3组坐标 既 1到3个中间航点
- List check = new List();//记录需要绕行的id组
- List checkEd = new List();//复查绕行未通过的id组
- //中段绕行 初始化
- double[] mRate = { .5, .6, .4, .7, .3 };//中点绕行的比例
- Vector3[] middlePos = SetMiddleCurvedValue(startPos, endPos, 0.5, 1);//加中间航点
- bool pa = false;
- strPrint("中(二)段绕行开始");
- while (true)//中段绕行循环
+ List vecs = new List();
+ // 计算圆的周长
+ double circumference = (double)(2 * Math.PI * radius);
+ // 计算弧上的点数
+ int numberOfPoints = (int)(circumference / chordLength);
+ // 计算每个点的弧度
+ double angleIncrement = (double)(2 * Math.PI / numberOfPoints);
+ // 生成点的坐标
+ for (int i = 0; i < numberOfPoints; i++)
{
- //前中后所有碰撞的飞机id
- check = ABNeedCheck(startPos, middlePos, endPos);
- //绕行
- if (check.Count != 0)//有碰撞
- {
- middlePos = ABypassB(startPos, middlePos, endPos, check, mRate);
- }
- //重新检查碰撞
- checkEd = ABNeedCheck(startPos, middlePos, endPos);
- if (checkEd.Count == 0)//如果绕行没有碰撞
- {
- strPrint("成功");
- middlePosS.Add(middlePos);//添加中间坐标组
- isSuccess = true;
- return middlePosS;//第一次绕行 没有碰撞 直接返回
- }
- if (check.SequenceEqual(checkEd))
- {
- if (pa)//判定第二次 check 和 checkEd一致
- {
- strPrint("一致跳出");//如果一个中间航点 算不过去 跳出然后 进行三段绕行
- break;//连续两次check 和 checkEd一致 跳出
- }
- pa = true;
- }
- else pa = false;
+ double angle = i * angleIncrement;
+ double x = radius * (double)Math.Cos(angle);
+ double y = radius * (double)Math.Sin(angle);
+ double z = 0.0f; // 如果是在平面上,Z 可能是 0
+ vecs.Add(new Vector3(x, y, z));
}
- //一段绕行初始化
- Vector3[] fMiddlePos = SetMiddleCurvedValue(startPos, middlePos, 0, 1);
- double[] fmRate = { 0, .05, .1, .15, .2 };//中点绕行的比例
- pa = false;
- check = ABNeedCheck(startPos, fMiddlePos, middlePos);
- if (check.Count != 0)//检测是否进行一段循环
+ return vecs;
+ }
+ ///
+ /// 获取a指向b的向量矩阵 ps:偏移次数 加1 会在终点前后往返偏移
+ ///
+ /// a向量
+ /// b向量
+ /// 默认中点位置比例
+ /// 偏移次数 从0开始,每+1在中点前后往返偏移
+ /// 偏移层高
+ /// 矩阵
+ public static Matrix GetBasisMatrix(Vector3 aVec, Vector3 bVec, double middleProportion = 0.5, int offCount = 0, double layHight = 220)
+ {
+ // 计算前向向量 k帽
+ Vector3 k_hat = (bVec - aVec).NormalizEd();
+ // 计算右向量,使用 Vector3.UnitY 作为上向量 i帽
+ Vector3 i_hat = CrossPro(Vector3.UnitY, k_hat).NormalizEd();
+ // 计算上向量 j帽
+ Vector3 j_hat = CrossPro(k_hat, i_hat);
+ //计算 对应的偏移比例
+ double length = (bVec - aVec).GetMag();
+ double offShift;//偏移比例
+ if (offCount % 2 == 1) //奇数
+ offShift = middleProportion + (offCount + 2) / 2 * layHight / length;
+ else //偶数
+ offShift = middleProportion - (offCount + 1) / 2 * layHight / length;
+ // 计算偏向量
+ Vector3 off = aVec + (bVec - aVec) * offShift;
+ // 构建矩阵
+ Matrix matrix = new Matrix
{
- strPrint("一段绕行开始");
- while (true)//一段绕行 循环体
+ M11 = k_hat.X,
+ M12 = k_hat.Y,
+ M13 = k_hat.Z,
+ M21 = i_hat.X,
+ M22 = i_hat.Y,
+ M23 = i_hat.Z,
+ M31 = j_hat.X,
+ M32 = j_hat.Y,
+ M33 = j_hat.Z,
+ M41 = off.X,
+ M42 = off.Y,
+ M43 = off.Z
+ };
+ return matrix;
+ }
+ ///
+ /// a b点中间的绕行航点列表
+ ///
+ /// 起点
+ /// 目标点
+ /// 中间航点位置比例
+ /// 传递圈函数的弦长 向量矩阵函数的层高
+ /// 绕行航点范围 ps:绕行中间航点肚子(值越大肚子越小)
+ ///
+ public static List GetRingVec(Vector3 aVec, Vector3 bVec, double middleProportion, double transfer = 220, double paunch = 3)
+ {
+ List ringVec = new List(); //记录所有绕行中间航点坐标
+ // 根据a到b的长度 算出中间绕行几圈
+ int ringCou = (int)Math.Ceiling(GageLength(aVec, bVec) / paunch / transfer); //绝对中心绕行的圈数 即中间航点的'肚子'大小
+ if (ringCou < 2) ringCou = 2; //最少两圈 两层
+ if (ringCou > 15) ringCou = 15; //最多15圈 15层
+ for (int z = 0; z < ringCou; z++) //迭代层
+ {
+ Matrix mat = GetBasisMatrix(aVec, bVec, middleProportion, z, transfer); //根据圈数越多 偏移层数也越多 即每层矩阵off位置
+ for (int i = 0; i < ringCou; i++) //迭代圈
{
- //前中后所有碰撞的飞机id
- check = ABNeedCheck(startPos, fMiddlePos, middlePos);
- if (check.Count != 0) fMiddlePos = ABypassB(startPos, fMiddlePos, middlePos, check, fmRate, 1500, 15);//有碰撞 绕行
- else//没有碰撞 添加返回值并跳出 一段绕行 循环
+ if (i != 0)
{
- strPrint("成功");
- isSuccess = true;
- middlePosS.Add(fMiddlePos);//添加一段 绕行结果
- break;
- }
- //重新检查碰撞
- checkEd = ABNeedCheck(startPos, fMiddlePos, middlePos);
- //多次绕行 结果相同 则判定未能成功通过 但是也会添加 绕行结果
- if (check.SequenceEqual(checkEd))//如果两次 碰撞检测结果完全相同
- {
- if (pa)//判定第二次 check 和 checkEd一致
+ List tempCi = GetVecsOnCircle(i * transfer, transfer);
+ foreach (Vector3 vec in tempCi)
{
- strPrint("一致跳出");//如果一个中间航点 算不过去 跳出然后 进行三段绕行
- isSuccess = false;
- middlePosS.Add(fMiddlePos);//添加一段 绕行结果
- break;//连续两次check 和 checkEd一致 跳出
+ ringVec.Add(vec.Multiply(mat));//按照矩阵旋转之后 添加到中间航点列表
}
- pa = true;
}
- else pa = false;
+ else
+ {
+ ringVec.Add(mat[3]); //第一次循环 并非圈 只在航线上 按层比例取点 即可
+ }
}
}
- //添加中段绕行结果
- middlePosS.Add(middlePos);
- //三段绕行初始化
- Vector3[] bMiddlePos = SetMiddleCurvedValue(middlePos, endPos, 1, 1);
- double[] bmRate = { 1, .95, 0.9, .85, .8 };//中点绕行的比例
- pa = false;
- check = ABNeedCheck(middlePos, bMiddlePos, endPos);
- if (check.Count != 0)//检测是否进行三段循环
- {
- strPrint("三段绕行开始");
- while (true)//一段绕行 循环体
- {
- //前中后所有碰撞的飞机id
- check = ABNeedCheck(middlePos, bMiddlePos, endPos);
- if (check.Count != 0) bMiddlePos = ABypassB(middlePos, bMiddlePos, endPos, check, bmRate, 1500, 15);//有碰撞 绕行
- else//没有碰撞 添加返回值并跳出 三段绕行 循环
- {
- strPrint("成功");
- isSuccess = true;
- middlePosS.Add(bMiddlePos);//添加三段 绕行结果
- break;
- }
- //重新检查碰撞
- checkEd = ABNeedCheck(middlePos, bMiddlePos, endPos);
- //多次绕行 结果相同 则判定未能成功通过 但是也会添加 绕行结果
- if (check.SequenceEqual(checkEd))//如果两次 碰撞检测结果完全相同
- {
- if (pa)//判定第二次 check 和 checkEd一致
- {
- strPrint("一致跳出");//如果一个中间航点 算不过去 跳出然后 进行三段绕行
- isSuccess = false;
- middlePosS.Add(bMiddlePos);//添加三段 绕行结果
- break;//连续两次check 和 checkEd一致 跳出
- }
- pa = true;
- }
- else pa = false;
- }
- }
- //三段绕行未果 进行三点同时绕行
-
- return middlePosS;
+ return ringVec;
}
}
}
\ No newline at end of file
diff --git a/FlyBase/FlyBase.csproj b/FlyBase/FlyBase.csproj
new file mode 100644
index 0000000..a87500d
--- /dev/null
+++ b/FlyBase/FlyBase.csproj
@@ -0,0 +1,49 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {626A9BFA-07DE-4063-A178-360EB7057ED6}
+ Library
+ Properties
+ FlyBase
+ FlyBase
+ v4.7.2
+ 512
+ true
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/FlyBase/Properties/AssemblyInfo.cs b/FlyBase/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..331cefd
--- /dev/null
+++ b/FlyBase/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// 有关程序集的一般信息由以下
+// 控制。更改这些特性值可修改
+// 与程序集关联的信息。
+[assembly: AssemblyTitle("FlyBase")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("FlyBase")]
+[assembly: AssemblyCopyright("Copyright © 2022")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// 将 ComVisible 设置为 false 会使此程序集中的类型
+//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
+//请将此类型的 ComVisible 特性设置为 true。
+[assembly: ComVisible(false)]
+
+// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
+[assembly: Guid("626a9bfa-07de-4063-a178-360eb7057ed6")]
+
+// 程序集的版本信息由下列四个值组成:
+//
+// 主版本
+// 次版本
+// 生成号
+// 修订号
+//
+//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
+//通过使用 "*",如下所示:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/FlyBase/Vector3.cs b/FlyBase/Vector3.cs
new file mode 100644
index 0000000..407a1ca
--- /dev/null
+++ b/FlyBase/Vector3.cs
@@ -0,0 +1,154 @@
+using System;
+
+namespace FlyBase
+{
+ public struct Vector3
+ {
+ public double X { get; set; }
+ public double Y { get; set; }
+ public double Z { get; set; }
+ ///
+ /// 构造 初始化
+ ///
+ /// x坐标
+ /// y坐标
+ /// z坐标
+ public Vector3(double x, double y, double z)
+ {
+ this.X = x;
+ this.Y = y;
+ this.Z = z;
+ }
+ //重载二元坐标加法+
+ public static Vector3 operator +(Vector3 v1, Vector3 v2)
+ {
+ return new Vector3(v1.X + v2.X, v1.Y + v2.Y, v1.Z + v2.Z);
+ }
+ //重载一元坐标加法+
+ public static Vector3 operator +(Vector3 v1, double i)
+ {
+ return new Vector3(v1.X + i, v1.Y + i, v1.Z + i);
+ }
+ //重载一元坐标加法+
+ public static Vector3 operator +(Vector3 v1, int i)
+ {
+ return new Vector3(v1.X + (double)i, v1.Y + (double)i, v1.Z + (double)i);
+ }
+ //重载二元坐标减法-
+ public static Vector3 operator -(Vector3 v1, Vector3 v2)
+ {
+ return new Vector3(v1.X - v2.X, v1.Y - v2.Y, v1.Z - v2.Z);
+ }
+ //重载一元坐标加法-
+ public static Vector3 operator -(Vector3 v1, double i)
+ {
+ return new Vector3(v1.X - i, v1.Y - i, v1.Z - i);
+ }
+ //重载一元坐标加法-
+ public static Vector3 operator -(Vector3 v1, int i)
+ {
+ return new Vector3(v1.X - (double)i, v1.Y - (double)i, v1.Z - (double)i);
+ }
+ //重载一元坐标乘法*
+ public static Vector3 operator *(Vector3 v1, double i)
+ {
+ return new Vector3(v1.X * i, v1.Y * i, v1.Z * i);
+ }
+ //重载一元坐标乘法*
+ public static Vector3 operator *(Vector3 v1, int i)
+ {
+ return new Vector3(v1.X * (double)i, v1.Y * (double)i, v1.Z * (double)i);
+ }
+ //重载一元坐标除法/
+ public static Vector3 operator /(Vector3 v1, double i)
+ {
+ return new Vector3(v1.X / i, v1.Y / i, v1.Z / i);
+ }
+ //重载一元坐标除法/
+ public static Vector3 operator /(Vector3 v1, int i)
+ {
+ return new Vector3(v1.X / (double)i, v1.Y / (double)i, v1.Z / (double)i);
+ }
+ //重载==
+ public static bool operator ==(Vector3 v1, Vector3 v2)
+ {
+ if (v1.X == v2.X && v1.Y == v2.Y && v1.Z == v2.Z) return true;
+ return false;
+ }
+ //重载!=
+ public static bool operator !=(Vector3 v1, Vector3 v2)
+ {
+ if (v1.X != v2.X || v1.Y != v2.Y || v1.Z != v2.Z) return true;
+ return false;
+ }
+ //模长
+ public double GetMag()
+ {
+ return Math.Sqrt(Math.Pow(this.X, 2) + Math.Pow(this.Y, 2) + Math.Pow(this.Z, 2));
+ }
+ ///
+ /// 标准化坐标
+ ///
+ /// 标准化单位
+ public void Normalize(double multiple = 1.0)
+ {
+ double magSq = Math.Pow(this.X, 2) + Math.Pow(this.Y, 2) + Math.Pow(this.Z, 2);
+ if (magSq > 0)
+ {
+ double oneOverMag = multiple / Math.Sqrt(magSq);
+ this.X *= oneOverMag;
+ this.Y *= oneOverMag;
+ this.Z *= oneOverMag;
+ }
+ }
+ ///
+ /// 标准化 返回一个标准化之后的值 不改变自身
+ ///
+ /// 标准化单位
+ /// 标准化之后的值
+ public Vector3 NormalizEd(double multiple = 1.0)
+ {
+ Vector3 re = new Vector3();
+ double magSq = Math.Pow(this.X, 2) + Math.Pow(this.Y, 2) + Math.Pow(this.Z, 2);
+ if (magSq > 0)
+ {
+ double oneOverMag = multiple / Math.Sqrt(magSq);
+ re.X = this.X * oneOverMag;
+ re.Y = this.Y * oneOverMag;
+ re.Z = this.Z * oneOverMag;
+ }
+ return re;
+ }
+ //归零 改变自身数值 一般配合归位使用
+ public void SetZero(Vector3 v2)
+ {
+ this.X -= v2.X;
+ this.Y -= v2.Y;
+ this.Z -= v2.Z;
+ }
+ //归零 返回一个归零值 不改变自身
+ public Vector3 SetZeroEd(Vector3 v2)
+ {
+ Vector3 re = new Vector3(this.X - v2.X, this.Y - v2.Y, this.Z - v2.Z);
+ return re;
+ }
+ //归位
+ public void SetFormerly(Vector3 v2)
+ {
+ this.X += v2.X;
+ this.Y += v2.Y;
+ this.Z += v2.Z;
+ }
+ ///
+ /// 打印坐标
+ ///
+ /// 坐标字符串
+ public string PosToString()
+ {
+ string x = Convert.ToString(this.X);
+ string y = Convert.ToString(this.Y);
+ string z = Convert.ToString(this.Z);
+ return string.Format($"X轴:{x} Y轴:{y} Z轴:{z}");
+ }
+ }
+}
\ No newline at end of file
diff --git a/FlyCube/App.config b/FlyCube/App.config
new file mode 100644
index 0000000..56efbc7
--- /dev/null
+++ b/FlyCube/App.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/FlyCube/App.xaml b/FlyCube/App.xaml
new file mode 100644
index 0000000..827d759
--- /dev/null
+++ b/FlyCube/App.xaml
@@ -0,0 +1,9 @@
+
+
+
+
+
diff --git a/FlyCube/App.xaml.cs b/FlyCube/App.xaml.cs
new file mode 100644
index 0000000..478bbaf
--- /dev/null
+++ b/FlyCube/App.xaml.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.Data;
+using System.Linq;
+using System.Threading.Tasks;
+using System.Windows;
+
+namespace FlyCube
+{
+ ///
+ /// App.xaml 的交互逻辑
+ ///
+ public partial class App : Application
+ {
+ }
+}
diff --git a/FlyCube/FlyCube.csproj b/FlyCube/FlyCube.csproj
new file mode 100644
index 0000000..9dbef46
--- /dev/null
+++ b/FlyCube/FlyCube.csproj
@@ -0,0 +1,122 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {B36F850B-75B9-42C9-9C48-88141AB6D4B1}
+ WinExe
+ FlyCube
+ FlyCube
+ v4.7.2
+ 512
+ {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ 4
+ true
+ true
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+ 4.0
+
+
+
+
+
+ packages\WpfAnimatedGif.2.0.2\lib\net40\WpfAnimatedGif.dll
+
+
+
+
+ MSBuild:Compile
+ Designer
+
+
+ Designer
+ MSBuild:Compile
+
+
+ MSBuild:Compile
+ Designer
+
+
+ App.xaml
+ Code
+
+
+ AxisControl.xaml
+
+
+ MainWindow.xaml
+ Code
+
+
+
+
+
+ Code
+
+
+ True
+ True
+ Resources.resx
+
+
+ True
+ Settings.settings
+ True
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+
+
+
+ SettingsSingleFileGenerator
+ Settings.Designer.cs
+
+
+
+
+
+
+
+ {c354fd6b-5863-4246-bb48-6df14a85c161}
+ FlieOperate
+
+
+ {626a9bfa-07de-4063-a178-360eb7057ed6}
+ FlyBase
+
+
+
+
+
\ No newline at end of file
diff --git a/FlyCube/FlyCube.sln b/FlyCube/FlyCube.sln
new file mode 100644
index 0000000..cda8c92
--- /dev/null
+++ b/FlyCube/FlyCube.sln
@@ -0,0 +1,40 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.7.34018.315
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FlyCube", "FlyCube.csproj", "{B36F850B-75B9-42C9-9C48-88141AB6D4B1}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FlyBase", "..\FlyBase\FlyBase.csproj", "{626A9BFA-07DE-4063-A178-360EB7057ED6}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FlieOperate", "..\FlieOperate\FlieOperate.csproj", "{C354FD6B-5863-4246-BB48-6DF14A85C161}"
+ ProjectSection(ProjectDependencies) = postProject
+ {626A9BFA-07DE-4063-A178-360EB7057ED6} = {626A9BFA-07DE-4063-A178-360EB7057ED6}
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {B36F850B-75B9-42C9-9C48-88141AB6D4B1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B36F850B-75B9-42C9-9C48-88141AB6D4B1}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B36F850B-75B9-42C9-9C48-88141AB6D4B1}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B36F850B-75B9-42C9-9C48-88141AB6D4B1}.Release|Any CPU.Build.0 = Release|Any CPU
+ {626A9BFA-07DE-4063-A178-360EB7057ED6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {626A9BFA-07DE-4063-A178-360EB7057ED6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {626A9BFA-07DE-4063-A178-360EB7057ED6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {626A9BFA-07DE-4063-A178-360EB7057ED6}.Release|Any CPU.Build.0 = Release|Any CPU
+ {C354FD6B-5863-4246-BB48-6DF14A85C161}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {C354FD6B-5863-4246-BB48-6DF14A85C161}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {C354FD6B-5863-4246-BB48-6DF14A85C161}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {C354FD6B-5863-4246-BB48-6DF14A85C161}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {AEC8BEB7-E150-46F0-829B-4B0984B4B59B}
+ EndGlobalSection
+EndGlobal
diff --git a/FlyCube/MainWindow.xaml b/FlyCube/MainWindow.xaml
index 9b60084..eec7bd5 100644
--- a/FlyCube/MainWindow.xaml
+++ b/FlyCube/MainWindow.xaml
@@ -21,6 +21,7 @@
+
\ No newline at end of file
diff --git a/FlyCube/MainWindow.xaml.cs b/FlyCube/MainWindow.xaml.cs
index cce5762..6628e70 100644
--- a/FlyCube/MainWindow.xaml.cs
+++ b/FlyCube/MainWindow.xaml.cs
@@ -19,12 +19,84 @@ using static FlieOperate.FcgmJsonModel.Tasks.SingleCopterInfos;
using FlyCube.Models;
using ControlLibrary;
using WpfAnimatedGif;//播放GIF
-
+using System.Security.Cryptography;
namespace FlyCube
{
public partial class MainWindow : Window
{
+ ///
+ /// 入口函数
+ ///
+ public MainWindow()
+ {
+ InitializeComponent();
+ //创建一个 主画布对象
+ TopCanvas = new MainCanvas(this.LayerPlane);
+ }
+ private void Del_Click(object sender, RoutedEventArgs e)
+ {
+ Vector3 a1 = new Vector3(0, 50, 220);
+ Vector3 a2 = new Vector3(0, 0, 0);
+ Vector3 a3 = new Vector3(0, 1000, 1000);
+ Vector3 a4 = new Vector3(1020, 0, 1000);
+ Vector3 a5 = new Vector3(1020, 0, 2240);
+ Vector3 a6 = new Vector3(1400, 2000, 4500);
+
+ Vector3 b1 = new Vector3(420, 0, 330);
+ Vector3 b2 = new Vector3(310, 0, 1400);
+ Vector3 b3 = new Vector3(120, 0, 4200);
+ Vector3 b4 = new Vector3(2330, 0, 7300);
+ Vector3 b5 = new Vector3(110, 0, 1400);
+ Vector3 b6 = new Vector3(1200, 0, 5200);
+ Vector3[] aa = new Vector3[] { a1, a2, a3, a4, a5, a6 };
+ Vector3[] bb = new Vector3[] { b1, b2, b3, b4, b5, b6 };
+
+ //FlyVecFun.GetRingVec(a1, a6, 0.5);
+ //return;
+ List a = FlyVecFun.GetRingVec(a1, a6, 0.5);
+ //foreach (int[] v in cc)
+ //{
+ // MessageBox.Show($"{ v[0].ToString()}----{v[1].ToString()}");
+ //}
+
+ //Vector3[] cc = FlyVecFun.ContactABOut(aa,bb);
+ //foreach (var item in a)
+ //{
+ // MessageBox.Show(item.PosToString());
+ //}
+ //MessageBox.Show($"{a[0].ToString()}---{a[1].ToString()}---{a[2].ToString()}---{a[3].ToString()}");
+ string str = "";
+ int id = 1;
+ foreach (Vector3 item in a)
+ {
+ str += id + " 0" + " " + item.X + " " + item.Y + " " + item.Z + "\r\n";
+ id++;
+ }
+ //for (int i = 0; i < 4; i++)
+ //{
+ // str += i + " 0" + " " + a[i].X + " " + a[i].Y + " " + a[i].Z + "\r\n";
+ //}
+ SaveFile("C:/Users/szdot/Desktop/del.txt", str);
+ }
+ //保存输出文本
+ private static void SaveFile(string filePath, string txtCon)
+ {
+ txtCon = txtCon.TrimEnd((char[])"\n\r".ToCharArray());//去除最后的回车符
+ Console.WriteLine(txtCon);
+ string stream = null;
+ if (File.Exists(filePath))
+ {
+ StreamReader reader = new StreamReader(filePath);
+ stream = reader.ReadToEnd();
+ reader.Close();
+ }
+ FileStream fs = new FileStream(filePath, FileMode.OpenOrCreate);
+ StreamWriter sw = new StreamWriter(fs);
+ sw.Write(txtCon);
+ sw.Close();
+ fs.Close();
+ }
///
/// 航点文件 模型对象
///
@@ -41,13 +113,6 @@ namespace FlyCube
/// 导入的gif路径
///
public string ImagePath { get; set; }
- public MainWindow()
- {
- InitializeComponent();
- //创建一个 主画布对象
- TopCanvas = new MainCanvas(this.LayerPlane);
-
- }
///
/// 导入航点
///
@@ -97,7 +162,6 @@ namespace FlyCube
PlaneVecOnCanvas[planeId] = v;
planeId++;
}
-
}
///
/// 输出航点
@@ -132,8 +196,11 @@ namespace FlyCube
}
}
-
-
+ ///
+ /// 渲染输出航点
+ ///
+ ///
+ ///
private void Render_Click(object sender, RoutedEventArgs e)
{
ImageUtility img = new ImageUtility(this.ImagePath);
@@ -141,7 +208,7 @@ namespace FlyCube
foreach (Vector3 item in PlaneVecOnCanvas)
{
List ledInfos = new List();
- Color[] colors = img.GetColorsForGifPos((int)item.X, (int)item.Y);
+ Color[] colors = img.GetColorsForGifPos((int)item.X, (int)item.Z);
string c = "";
foreach (var color in colors)
{
@@ -150,20 +217,20 @@ namespace FlyCube
//添加灯光信息
LedInfos led = new LedInfos();
led.Delay = 0.1;
- led.LEDMode = 0;
+ led.LEDMode = (int)LightClass.常亮;
led.LEDInterval = 0.0;
led.LEDRate = 0;
led.LEDTimes = 0;
led.LEDRGB = color.ToString().Remove(0, 3);
ledInfos.Add(led);
- //记录这一帧颜色 用于下次循环和 这一帧进行对比
+ //记录这一帧颜色 用于下次循环时和 这一帧进行对比
c = color.ToString().Remove(0, 3);
}
else//如果和上一帧颜色一样 则不进行Add 并把上一帧的 灯光延时自加0.1秒
{
- ledInfos[ledInfos.Count-1].Delay += 0.1;
+ ledInfos[ledInfos.Count - 1].Delay += 0.1;
}
-
+
}
this.FcgmInfo.tasks[2].singleCopterInfos[id].ledInfos = ledInfos;
id++;
@@ -171,7 +238,7 @@ namespace FlyCube
MessageBox.Show("成功");
}
-
+
}
///
/// 灯光 组
diff --git a/FlyCube/Properties/AssemblyInfo.cs b/FlyCube/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..c80e3ce
--- /dev/null
+++ b/FlyCube/Properties/AssemblyInfo.cs
@@ -0,0 +1,55 @@
+using System.Reflection;
+using System.Resources;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Windows;
+
+// 有关程序集的一般信息由以下
+// 控制。更改这些特性值可修改
+// 与程序集关联的信息。
+[assembly: AssemblyTitle("FlyCube")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("FlyCube")]
+[assembly: AssemblyCopyright("Copyright © 2022")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// 将 ComVisible 设置为 false 会使此程序集中的类型
+//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
+//请将此类型的 ComVisible 特性设置为 true。
+[assembly: ComVisible(false)]
+
+//若要开始生成可本地化的应用程序,请设置
+//.csproj 文件中的 CultureYouAreCodingWith
+//例如,如果您在源文件中使用的是美国英语,
+//使用的是美国英语,请将 设置为 en-US。 然后取消
+//对以下 NeutralResourceLanguage 特性的注释。 更新
+//以下行中的“en-US”以匹配项目文件中的 UICulture 设置。
+
+//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
+
+
+[assembly: ThemeInfo(
+ ResourceDictionaryLocation.None, //主题特定资源词典所处位置
+ //(未在页面中找到资源时使用,
+ //或应用程序资源字典中找到时使用)
+ ResourceDictionaryLocation.SourceAssembly //常规资源词典所处位置
+ //(未在页面中找到资源时使用,
+ //、应用程序或任何主题专用资源字典中找到时使用)
+)]
+
+
+// 程序集的版本信息由下列四个值组成:
+//
+// 主版本
+// 次版本
+// 生成号
+// 修订号
+//
+//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
+//通过使用 "*",如下所示:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/FlyCube/Properties/Resources.Designer.cs b/FlyCube/Properties/Resources.Designer.cs
new file mode 100644
index 0000000..4029942
--- /dev/null
+++ b/FlyCube/Properties/Resources.Designer.cs
@@ -0,0 +1,70 @@
+//------------------------------------------------------------------------------
+//
+// 此代码由工具生成。
+// 运行时版本: 4.0.30319.42000
+//
+// 对此文件的更改可能导致不正确的行为,如果
+// 重新生成代码,则所做更改将丢失。
+//
+//------------------------------------------------------------------------------
+
+
+namespace FlyCube.Properties
+{
+ ///
+ /// 强类型资源类,用于查找本地化字符串等。
+ ///
+ // 此类是由 StronglyTypedResourceBuilder
+ // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
+ // 若要添加或删除成员,请编辑 .ResX 文件,然后重新运行 ResGen
+ // (以 /str 作为命令选项),或重新生成 VS 项目。
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources
+ {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources()
+ {
+ }
+
+ ///
+ /// 返回此类使用的缓存 ResourceManager 实例。
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager
+ {
+ get
+ {
+ if ((resourceMan == null))
+ {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("FlyCube.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// 重写当前线程的 CurrentUICulture 属性,对
+ /// 使用此强类型资源类的所有资源查找执行重写。
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture
+ {
+ get
+ {
+ return resourceCulture;
+ }
+ set
+ {
+ resourceCulture = value;
+ }
+ }
+ }
+}
diff --git a/FlyCube/Properties/Resources.resx b/FlyCube/Properties/Resources.resx
new file mode 100644
index 0000000..af7dbeb
--- /dev/null
+++ b/FlyCube/Properties/Resources.resx
@@ -0,0 +1,117 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/FlyCube/Properties/Settings.Designer.cs b/FlyCube/Properties/Settings.Designer.cs
new file mode 100644
index 0000000..f74ee18
--- /dev/null
+++ b/FlyCube/Properties/Settings.Designer.cs
@@ -0,0 +1,29 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+
+namespace FlyCube.Properties
+{
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
+ internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
+ {
+
+ private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+
+ public static Settings Default
+ {
+ get
+ {
+ return defaultInstance;
+ }
+ }
+ }
+}
diff --git a/FlyCube/Properties/Settings.settings b/FlyCube/Properties/Settings.settings
new file mode 100644
index 0000000..033d7a5
--- /dev/null
+++ b/FlyCube/Properties/Settings.settings
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/FlyCube/packages.config b/FlyCube/packages.config
new file mode 100644
index 0000000..8fc7f38
--- /dev/null
+++ b/FlyCube/packages.config
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file