217 lines
6.1 KiB
C#
217 lines
6.1 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
|
|
namespace AibisDream
|
|
{
|
|
public class ShaftGraph
|
|
{
|
|
// 顶点数量
|
|
int vertexSize;
|
|
|
|
// 顶点Map
|
|
Shaft[] vertexArray;
|
|
|
|
// 邻接表
|
|
float[,] edgeTable;
|
|
|
|
// 遍历记录
|
|
bool[] vertexRecordArray;
|
|
|
|
// 动力轴序号
|
|
int rootIdx;
|
|
|
|
public ShaftGraph(Shaft[] shafts)
|
|
{
|
|
// 为轴赋值
|
|
vertexSize = shafts.Length;
|
|
vertexRecordArray = new bool[vertexSize];
|
|
vertexArray = shafts;
|
|
foreach (var shaft in vertexArray)
|
|
{
|
|
shaft.InitShaft();
|
|
}
|
|
|
|
// 寻找唯一的驱动轴序号
|
|
rootIdx = FindDriverIdx();
|
|
|
|
// 生成边邻接表
|
|
GeneEdgeTable();
|
|
|
|
UpdateSpeed();
|
|
}
|
|
|
|
private int FindDriverIdx()
|
|
{
|
|
for (int i = 0; i < vertexSize; i++)
|
|
{
|
|
if (vertexArray[i].shaftType == ShaftType.Driver)
|
|
{
|
|
return i;
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 生成边邻接表
|
|
/// </summary>
|
|
private void GeneEdgeTable()
|
|
{
|
|
edgeTable = new float[vertexSize, vertexSize];
|
|
|
|
for (int i = 0; i < vertexSize - 1; i++)
|
|
{
|
|
for (int j = i + 1; j < vertexSize; j++)
|
|
{
|
|
// 判断两个Shaft是否临接
|
|
if (Shaft.IsShaftConnected(vertexArray[i], vertexArray[j]))
|
|
{
|
|
edgeTable[i, j] = Shaft.CalcAngularVelocityRatio(vertexArray[i], vertexArray[j]);
|
|
edgeTable[j, i] = Shaft.CalcAngularVelocityRatio(vertexArray[j], vertexArray[i]);
|
|
}
|
|
else
|
|
{
|
|
edgeTable[i, j] = 0;
|
|
edgeTable[j, i] = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 某个轴上齿轮发生变化时更新临接关系
|
|
/// </summary>
|
|
/// <param name="instanceID">轴ID</param>
|
|
public void ChangeVertex(int instanceID)
|
|
{
|
|
// 找到对应idx
|
|
int idx = TranInstanceIDToIdx(instanceID);
|
|
|
|
// 更新该节点对应的邻接表
|
|
for (int i = 0; i < vertexSize; i++)
|
|
{
|
|
// 遇到自身跳过
|
|
if (i == idx)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// 判断两个Shaft是否临接
|
|
if (Shaft.IsShaftConnected(vertexArray[idx], vertexArray[i]))
|
|
{
|
|
edgeTable[idx, i] = Shaft.CalcAngularVelocityRatio(vertexArray[idx], vertexArray[i]);
|
|
edgeTable[i, idx] = Shaft.CalcAngularVelocityRatio(vertexArray[i], vertexArray[idx]);
|
|
}
|
|
else
|
|
{
|
|
edgeTable[idx, i] = 0;
|
|
edgeTable[i, idx] = 0;
|
|
}
|
|
}
|
|
|
|
UpdateSpeed();
|
|
}
|
|
|
|
private int TranInstanceIDToIdx(int instanceID)
|
|
{
|
|
// 查找对应的序号
|
|
int idx = -1;
|
|
for (int i = 0; i < vertexSize; i++)
|
|
{
|
|
if (instanceID == vertexArray[i].GetInstanceID())
|
|
{
|
|
idx = i;
|
|
break;
|
|
}
|
|
}
|
|
return idx;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 更新当前所有轴的速度
|
|
/// </summary>
|
|
public void UpdateSpeed()
|
|
{
|
|
// 清除遍历记录
|
|
Array.Clear(vertexRecordArray, 0, vertexSize);
|
|
// 从驱动轴开始计算速度
|
|
UpdateShaftSpeedByIdx(rootIdx);
|
|
}
|
|
|
|
private void UpdateShaftSpeedByIdx(int idx)
|
|
{
|
|
// 已知当前齿轮速度
|
|
float currentSpeed = vertexArray[idx].Speed;
|
|
|
|
for (int i = 0; i < vertexSize; i++)
|
|
{
|
|
// 遍历临接齿轮
|
|
if (i != idx && edgeTable[idx, i] > 0)
|
|
{
|
|
// 已遍历过就跳过
|
|
if (vertexRecordArray[idx])
|
|
{
|
|
continue;
|
|
}
|
|
|
|
Debug.Log(idx);
|
|
|
|
// 更新速度
|
|
vertexArray[i].Speed = currentSpeed * edgeTable[idx, i];
|
|
// 继续寻找相邻齿轮
|
|
//UpdateShaftSpeedByIdx(i);
|
|
// 已遍历的轴加上标记
|
|
vertexRecordArray[i] = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 查询可吸附的轴
|
|
/// </summary>
|
|
/// <param name="pos">齿轮位置</param>
|
|
/// <param name="gearRadius">齿轮半径</param>
|
|
/// <returns>吸附轴</returns>
|
|
public Shaft QuerySnapShaft(Vector3 pos, float gearRadius)
|
|
{
|
|
if (vertexArray == null || vertexArray.Length == 0)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
// 查询距离最近的,可吸附的Shaft
|
|
Shaft closestShaft = null;
|
|
float minDistence = -1;
|
|
foreach (var vertex in vertexArray)
|
|
{
|
|
if (vertex.shaftType == ShaftType.Pluggable && !vertex.HasChildGear())
|
|
{
|
|
float tempDis = Vector3.Distance(vertex.transform.position, pos);
|
|
if (minDistence < 0 || tempDis < minDistence)
|
|
{
|
|
closestShaft = vertex;
|
|
minDistence = tempDis;
|
|
}
|
|
}
|
|
}
|
|
|
|
// 没查到就返回空
|
|
if (closestShaft == null) { return null; }
|
|
|
|
// 查到了就返回是否吸附
|
|
if (minDistence < gearRadius)
|
|
{
|
|
return closestShaft;
|
|
}
|
|
else
|
|
{
|
|
return null;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|