754 lines
18 KiB
C#
754 lines
18 KiB
C#
using XericLibrary.Runtime.MacroLibrary;
|
||
using XericLibrary.Runtime.Type;
|
||
|
||
using System.Collections;
|
||
using System.Collections.Generic;
|
||
using System.Drawing;
|
||
using System.Runtime.CompilerServices;
|
||
|
||
using UnityEngine;
|
||
using UnityEngine.UIElements;
|
||
|
||
namespace XericLibrary.Runtime.MacroLibrary
|
||
{
|
||
public class NeighborGrid<T> : WeaklyObject,
|
||
IEnumerable<KeyValuePair<int, List<T>>>
|
||
{
|
||
#region 字段属性
|
||
|
||
private Vector3 position;
|
||
private Vector3 cellSize;
|
||
private Vector3Int numCells;
|
||
private int maxNeighbor = 8;
|
||
|
||
|
||
public Vector3 Position
|
||
{
|
||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||
get => position;
|
||
}
|
||
public Vector3 CellSize
|
||
{
|
||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||
get => cellSize;
|
||
}
|
||
public Vector3Int NumCells
|
||
{
|
||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||
get => numCells;
|
||
}
|
||
|
||
|
||
internal System.Random random = new System.Random();
|
||
private int NeighborRandomIndex
|
||
{
|
||
get => random.Next(maxNeighbor);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 网格系统存储地
|
||
/// </summary>
|
||
private Dictionary<int, List<T>> grid = new Dictionary<int, List<T>>();
|
||
|
||
/// <summary>
|
||
/// 网格的总尺寸
|
||
/// </summary>
|
||
public Vector3 Fullsize
|
||
{
|
||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||
get => cellSize.Mul(numCells);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 此网格系统转为盒体范围
|
||
/// </summary>
|
||
public Bounds GridBounds
|
||
{
|
||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||
get => new Bounds(position, Fullsize / 2);
|
||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||
set
|
||
{
|
||
position = value.center;
|
||
cellSize = (value.size * 2).Div(numCells);
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 构造
|
||
|
||
/// <summary>
|
||
/// 临近网格
|
||
/// </summary>
|
||
/// <param name="position">网格原点坐标</param>
|
||
/// <param name="cellSize">网格晶格尺寸</param>
|
||
/// <param name="fullSize">网格总尺寸</param>
|
||
/// <param name="maxNeighbor">单个晶格内最大邻居数量</param>
|
||
public NeighborGrid(Vector3 position, Vector3 cellSize, Vector3 fullSize, int maxNeighbor = 8)
|
||
{
|
||
this.position = position;
|
||
this.cellSize = cellSize;
|
||
this.numCells = fullSize.Div(cellSize).FloorToInt().Max(Vector3Int.one);
|
||
this.maxNeighbor = maxNeighbor;
|
||
|
||
Debug.Log($"原点:{position}, 晶格尺寸{cellSize}, 数量:{numCells}");
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 类内类
|
||
|
||
/// <summary>
|
||
/// 网格索引
|
||
/// </summary>
|
||
public struct NeighborGridIndex
|
||
{
|
||
#region 字段属性
|
||
|
||
private NeighborGrid<T> grid;
|
||
|
||
private NeighborGridSpace drivenSpace;
|
||
|
||
private object drivenIndex;
|
||
|
||
#endregion
|
||
|
||
#region 构造
|
||
|
||
public NeighborGridIndex(NeighborGrid<T> grid)
|
||
{
|
||
this.grid = grid;
|
||
drivenSpace = (NeighborGridSpace)(-1);
|
||
drivenIndex = null;
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 方法
|
||
|
||
/// <summary>
|
||
/// 获取为 世界空间
|
||
/// </summary>
|
||
/// <param name="world"></param>
|
||
public Vector3 GetDrivenAsWorld()
|
||
{
|
||
DrivenTransformTo(NeighborGridSpace.World);
|
||
return (Vector3)drivenIndex;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取为 网格系统本地坐标空间
|
||
/// </summary>
|
||
/// <param name="simulation"></param>
|
||
public Vector3 GetDrivenAsSimulation()
|
||
{
|
||
DrivenTransformTo(NeighborGridSpace.Simulation);
|
||
return (Vector3)drivenIndex;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取为 网格系统本地单位空间
|
||
/// </summary>
|
||
/// <param name="unit"></param>
|
||
public Vector3 GetDrivenAsUnit()
|
||
{
|
||
DrivenTransformTo(NeighborGridSpace.Unit);
|
||
return (Vector3)drivenIndex;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取为 三维索引
|
||
/// </summary>
|
||
/// <param name="world"></param>
|
||
public Vector3Int GetDrivenAsIndex()
|
||
{
|
||
DrivenTransformTo(NeighborGridSpace.Index);
|
||
return (Vector3Int)drivenIndex;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取为 线性索引
|
||
/// </summary>
|
||
/// <param name="world"></param>
|
||
public int GetDrivenAsLinear()
|
||
{
|
||
DrivenTransformTo(NeighborGridSpace.Linear);
|
||
return (int)drivenIndex;
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 设置为 世界空间
|
||
/// </summary>
|
||
/// <param name="world"></param>
|
||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||
public NeighborGridIndex SetDrivenAsWorld(Vector3 world)
|
||
{
|
||
drivenIndex = world;
|
||
drivenSpace = NeighborGridSpace.World;
|
||
return this;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 设置为 网格系统本地坐标空间
|
||
/// </summary>
|
||
/// <param name="simulation"></param>
|
||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||
public NeighborGridIndex SetDrivenAsSimulation(Vector3 simulation)
|
||
{
|
||
drivenIndex = simulation;
|
||
drivenSpace = NeighborGridSpace.Simulation;
|
||
return this;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 设置为 网格系统本地单位空间
|
||
/// </summary>
|
||
/// <param name="unit"></param>
|
||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||
public NeighborGridIndex SetDrivenAsUnit(Vector3 unit)
|
||
{
|
||
drivenIndex = unit;
|
||
drivenSpace = NeighborGridSpace.Unit;
|
||
return this;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 设置为 三维索引
|
||
/// </summary>
|
||
/// <param name="world"></param>
|
||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||
public NeighborGridIndex SetDrivenAsIndex(Vector3Int index)
|
||
{
|
||
drivenIndex = index;
|
||
drivenSpace = NeighborGridSpace.Index;
|
||
return this;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 设置为 线性索引
|
||
/// </summary>
|
||
/// <param name="world"></param>
|
||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||
public NeighborGridIndex SetDrivenAsLinear(int linear)
|
||
{
|
||
drivenIndex = linear;
|
||
drivenSpace = NeighborGridSpace.Linear;
|
||
return this;
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 转换当前索引到目标空间
|
||
/// </summary>
|
||
/// <param name="targetSpace"></param>
|
||
public NeighborGridIndex DrivenTransformTo(NeighborGridSpace targetSpace)
|
||
{
|
||
switch(targetSpace)
|
||
{
|
||
case NeighborGridSpace.World:
|
||
TransformToWorld();
|
||
break;
|
||
|
||
case NeighborGridSpace.Simulation:
|
||
TransformToSimulation();
|
||
break;
|
||
|
||
case NeighborGridSpace.Unit:
|
||
TransformToUnit();
|
||
break;
|
||
|
||
case NeighborGridSpace.Index:
|
||
TransformToIndex();
|
||
break;
|
||
|
||
case NeighborGridSpace.Linear:
|
||
TransformToLiear();
|
||
break;
|
||
|
||
default:
|
||
throw new System.Exception("转换空间是无效的");
|
||
}
|
||
return this;
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 将当前的目标转换到世界空间
|
||
/// </summary>
|
||
private void TransformToWorld()
|
||
{
|
||
switch(drivenSpace)
|
||
{
|
||
case NeighborGridSpace.World:
|
||
drivenSpace = NeighborGridSpace.World;
|
||
break;
|
||
|
||
case NeighborGridSpace.Simulation:
|
||
drivenIndex = grid.SimulationToWorld((Vector3)drivenIndex);
|
||
goto case NeighborGridSpace.World;
|
||
|
||
case NeighborGridSpace.Unit:
|
||
drivenIndex = grid.UnitToSimulation((Vector3)drivenIndex);
|
||
goto case NeighborGridSpace.Simulation;
|
||
|
||
case NeighborGridSpace.Index:
|
||
drivenIndex = grid.IndexToUnit((Vector3Int)drivenIndex);
|
||
goto case NeighborGridSpace.Unit;
|
||
|
||
case NeighborGridSpace.Linear:
|
||
drivenIndex = grid.LinearToIndex((int)drivenIndex);
|
||
goto case NeighborGridSpace.Index;
|
||
|
||
default:
|
||
throw new System.Exception("转换空间是无效的");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 将当前的目标转换到本地空间
|
||
/// </summary>
|
||
private void TransformToSimulation()
|
||
{
|
||
switch(drivenSpace)
|
||
{
|
||
case NeighborGridSpace.World:
|
||
drivenIndex = grid.WorldToSimulation((Vector3)drivenIndex);
|
||
goto case NeighborGridSpace.Simulation;
|
||
|
||
case NeighborGridSpace.Simulation:
|
||
drivenSpace = NeighborGridSpace.Simulation;
|
||
break;
|
||
|
||
case NeighborGridSpace.Unit:
|
||
drivenIndex = grid.UnitToSimulation((Vector3)drivenIndex);
|
||
goto case NeighborGridSpace.Simulation;
|
||
|
||
case NeighborGridSpace.Index:
|
||
drivenIndex = grid.IndexToUnit((Vector3Int)drivenIndex);
|
||
goto case NeighborGridSpace.Unit;
|
||
|
||
case NeighborGridSpace.Linear:
|
||
drivenIndex = grid.LinearToIndex((int)drivenIndex);
|
||
goto case NeighborGridSpace.Index;
|
||
|
||
default:
|
||
throw new System.Exception("转换空间是无效的");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 将当前的目标转换到单位空间
|
||
/// </summary>
|
||
private void TransformToUnit()
|
||
{
|
||
switch(drivenSpace)
|
||
{
|
||
case NeighborGridSpace.World:
|
||
drivenIndex = grid.WorldToSimulation((Vector3)drivenIndex);
|
||
goto case NeighborGridSpace.Simulation;
|
||
|
||
case NeighborGridSpace.Simulation:
|
||
drivenIndex = grid.SimulationToUnit((Vector3)drivenIndex);
|
||
goto case NeighborGridSpace.Unit;
|
||
|
||
case NeighborGridSpace.Unit:
|
||
drivenSpace = NeighborGridSpace.Unit;
|
||
break;
|
||
|
||
case NeighborGridSpace.Index:
|
||
drivenIndex = grid.IndexToUnit((Vector3Int)drivenIndex);
|
||
goto case NeighborGridSpace.Unit;
|
||
|
||
case NeighborGridSpace.Linear:
|
||
drivenIndex = grid.LinearToIndex((int)drivenIndex);
|
||
goto case NeighborGridSpace.Index;
|
||
|
||
default:
|
||
throw new System.Exception("转换空间是无效的");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 将当前的目标转换到三维索引
|
||
/// </summary>
|
||
private void TransformToIndex()
|
||
{
|
||
switch(drivenSpace)
|
||
{
|
||
case NeighborGridSpace.World:
|
||
drivenIndex = grid.WorldToSimulation((Vector3)drivenIndex);
|
||
goto case NeighborGridSpace.Simulation;
|
||
|
||
case NeighborGridSpace.Simulation:
|
||
drivenIndex = grid.SimulationToUnit((Vector3)drivenIndex);
|
||
goto case NeighborGridSpace.Unit;
|
||
|
||
case NeighborGridSpace.Unit:
|
||
drivenIndex = grid.UnitToIndex((Vector3)drivenIndex);
|
||
goto case NeighborGridSpace.Index;
|
||
|
||
case NeighborGridSpace.Index:
|
||
drivenSpace = NeighborGridSpace.Index;
|
||
break;
|
||
|
||
case NeighborGridSpace.Linear:
|
||
drivenIndex = grid.LinearToIndex((int)drivenIndex);
|
||
goto case NeighborGridSpace.Index;
|
||
|
||
default:
|
||
throw new System.Exception("转换空间是无效的");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 将当前的目标转换到线性索引
|
||
/// </summary>
|
||
private void TransformToLiear()
|
||
{
|
||
switch(drivenSpace)
|
||
{
|
||
case NeighborGridSpace.World:
|
||
drivenIndex = grid.WorldToSimulation((Vector3)drivenIndex);
|
||
goto case NeighborGridSpace.Simulation;
|
||
|
||
case NeighborGridSpace.Simulation:
|
||
drivenIndex = grid.SimulationToUnit((Vector3)drivenIndex);
|
||
goto case NeighborGridSpace.Unit;
|
||
|
||
case NeighborGridSpace.Unit:
|
||
drivenIndex = grid.UnitToIndex((Vector3)drivenIndex);
|
||
goto case NeighborGridSpace.Index;
|
||
|
||
case NeighborGridSpace.Index:
|
||
drivenIndex = grid.IndexToLinear((Vector3Int)drivenIndex);
|
||
break;
|
||
|
||
case NeighborGridSpace.Linear:
|
||
drivenSpace = NeighborGridSpace.Linear;
|
||
break;
|
||
|
||
default:
|
||
throw new System.Exception("转换空间是无效的");
|
||
}
|
||
|
||
}
|
||
|
||
#endregion
|
||
|
||
}
|
||
|
||
/// <summary>
|
||
/// 临近网络空间枚举
|
||
/// </summary>
|
||
public enum NeighborGridSpace
|
||
{
|
||
World,
|
||
Simulation,
|
||
Unit,
|
||
Index,
|
||
Linear
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 索引变换
|
||
|
||
/// <summary>
|
||
/// 世界空间 变换为 网格系统本地坐标空间
|
||
/// </summary>
|
||
/// <param name="world">项目的世界空间坐标</param>
|
||
/// <returns></returns>
|
||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||
public Vector3 WorldToSimulation(Vector3 world)
|
||
=> world - position - (-Fullsize / 2);
|
||
|
||
/// <summary>
|
||
/// 网格系统本地坐标空间 变换为 世界空间
|
||
/// </summary>
|
||
/// <param name="world">项目的世界空间坐标</param>
|
||
/// <returns></returns>
|
||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||
public Vector3 SimulationToWorld(Vector3 simulation)
|
||
=> simulation + position + (-Fullsize / 2);
|
||
|
||
|
||
/// <summary>
|
||
/// 网格系统本地坐标空间 变换为 网格系统本地单位空间
|
||
/// </summary>
|
||
/// <param name="simulation">网格系统本地坐标空间</param>
|
||
/// <returns></returns>
|
||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||
public Vector3 SimulationToUnit(Vector3 simulation)
|
||
=> simulation.Div(Fullsize);
|
||
|
||
/// <summary>
|
||
/// 网格系统本地坐标空间 变换为 网格系统本地单位空间
|
||
/// </summary>
|
||
/// <param name="simulation">网格系统本地坐标空间</param>
|
||
/// <returns></returns>
|
||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||
public Vector3 UnitToSimulation(Vector3 unit)
|
||
=> unit.Mul(Fullsize);
|
||
|
||
|
||
/// <summary>
|
||
/// 网格系统本地单位空间 变换为 三维索引
|
||
/// </summary>
|
||
/// <param name="unit">网格系统本地单位空间</param>
|
||
/// <returns></returns>
|
||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||
public Vector3Int UnitToIndex(Vector3 unit)
|
||
=> unit.IsInUnit() ? unit.Mul(numCells).FloorToInt() : MacroMath.Vector3Int_Negate;
|
||
|
||
/// <summary>
|
||
/// 三维索引 变换为 网格系统本地单位空间
|
||
/// </summary>
|
||
/// <param name="index">三维索引</param>
|
||
/// <returns></returns>
|
||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||
public Vector3 IndexToUnit(Vector3Int index)
|
||
{
|
||
if(index.IsValid())
|
||
{
|
||
Vector3 unit = ((Vector3)index).Div(numCells);
|
||
unit.x = numCells.x == 1 && unit.x <= 0 ? .5f : unit.x;
|
||
unit.y = numCells.y == 1 && unit.y <= 0 ? .5f : unit.y;
|
||
unit.z = numCells.z == 1 && unit.z <= 0 ? .5f : unit.z;
|
||
return unit;
|
||
}
|
||
return MacroMath.Vector3Int_Negate;
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 网格系统本地单位空间 变换为 线性索引
|
||
/// </summary>
|
||
/// <param name="unit">网格系统本地坐标空间</param>
|
||
/// <returns></returns>
|
||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||
public int UnitToLinear(Vector3 unit)
|
||
{
|
||
if(unit.IsInUnit())
|
||
{
|
||
return IndexToLinear(UnitToIndex(unit));
|
||
}
|
||
return -1;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 三维索引 变换为 线性索引
|
||
/// </summary>
|
||
/// <param name="index">三维索引</param>
|
||
/// <returns></returns>
|
||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||
public int IndexToLinear(Vector3Int index)
|
||
{
|
||
if(index.IsValid() && index.IsInIndexRange(numCells))
|
||
{
|
||
return (int)(index.x +
|
||
(index.y * numCells.x) +
|
||
(index.z * numCells.y * numCells.x));
|
||
}
|
||
return -1;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 根据线性索引获取网格中索引偏移量
|
||
/// </summary>
|
||
/// <param name="linear">线性索引</param>
|
||
/// <param name="side">边长</param>
|
||
/// <returns></returns>
|
||
public Vector3Int LinearToGridIndex(int linear, int side)
|
||
{
|
||
return new Vector3Int(linear % side, linear / side, linear / side.Quad());
|
||
}
|
||
|
||
/// <summary>
|
||
/// 线性索引 变换为 三维索引
|
||
/// </summary>
|
||
/// <param name="linear">线性索引</param>
|
||
/// <returns></returns>
|
||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||
public Vector3Int LinearToIndex(int linear)
|
||
{
|
||
int z = linear / (numCells.x * numCells.y);
|
||
int y = (linear - (z * numCells.x * numCells.y)) / numCells.x;
|
||
int x = linear - (z * numCells.x * numCells.y) - (y * numCells.x);
|
||
|
||
return new Vector3Int(x, y, z);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 线性索引 变换为 网格系统本地单位空间
|
||
/// </summary>
|
||
/// <param name="linear">线性索引</param>
|
||
/// <returns></returns>
|
||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||
public Vector3 LinearToUnit(int linear)
|
||
{
|
||
Debug.Log($"线性转索引空间{LinearToIndex(linear)},再转单位");
|
||
return IndexToUnit(LinearToIndex(linear));
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 增删查
|
||
|
||
/// <summary>
|
||
/// 清空网格
|
||
/// </summary>
|
||
public void Clean()
|
||
{
|
||
grid.Clear();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 在给定索引处添加一个项目
|
||
/// </summary>
|
||
/// <param name="linear">索引</param>
|
||
/// <returns>返回是否添加成功</returns>
|
||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||
public bool Insert(int linear, T obj)
|
||
{
|
||
if(linear < 0)
|
||
return false;
|
||
if(grid.ContainsKey(linear))
|
||
{
|
||
int index = grid[linear].IndexOf(obj);
|
||
if(index < 0)
|
||
{
|
||
grid[linear].Add(obj);
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
else
|
||
{
|
||
grid.Add(linear, new List<T> { obj });
|
||
return true;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 移除给定索引处的项目
|
||
/// </summary>
|
||
/// <param name="linear">索引</param>
|
||
/// <param name="obj">项目</param>
|
||
/// <returns>返回是否移除成功</returns>
|
||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||
public bool Remove(int linear, T obj)
|
||
{
|
||
if(grid.ContainsKey(linear))
|
||
{
|
||
bool resualt = grid[linear].Remove(obj);
|
||
if(grid[linear].Count <= 0)
|
||
grid.Remove(linear);
|
||
return resualt;
|
||
}
|
||
return false;
|
||
}
|
||
/// <summary>
|
||
/// 移除给定索引下所有项目
|
||
/// </summary>
|
||
/// <param name="linear">索引</param>
|
||
/// <returns>返回是否移除成功</returns>
|
||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||
public void Remove(int linear)
|
||
{
|
||
if(grid[linear] is not null)
|
||
{
|
||
grid[linear].Clear();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 查询给定索引处是否存在项目
|
||
/// </summary>
|
||
/// <param name="linear">索引</param>
|
||
/// <param name="obj">项目</param>
|
||
/// <returns>返回项目是否存在</returns>
|
||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||
public bool Contains(int linear, T obj)
|
||
{
|
||
if(grid[linear] is not null)
|
||
{
|
||
return grid[linear].Contains(obj);
|
||
}
|
||
return false;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 忽略限制获取所有的邻居
|
||
/// <code>
|
||
/// 警告:潜在的高性能开销
|
||
/// </code>
|
||
/// </summary>
|
||
/// <param name="linear"></param>
|
||
/// <returns></returns>
|
||
public bool GetAllNeighbor(int linear, out List<T> values)
|
||
{
|
||
return grid.TryGetValue(linear, out values);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取允许范围内的邻居
|
||
/// </summary>
|
||
/// <param name="linear">所在位置的索引</param>
|
||
/// <returns></returns>
|
||
public IEnumerable<T> GetNeighbor(int linear)
|
||
{
|
||
int startIndex = NeighborRandomIndex;
|
||
int count = grid[linear].Count;
|
||
for(int i = 0; i < maxNeighbor; i++)
|
||
{
|
||
yield return grid[linear][(startIndex + i) % count];
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取半径内所有允许的邻居
|
||
/// </summary>
|
||
/// <param name="linear">所在位置的索引</param>
|
||
/// <param name="range">检查的范围</param>
|
||
/// <returns></returns>
|
||
public IEnumerable<T> GetNeighbor(int linear, int radius)
|
||
{
|
||
int side = radius * 2 + 1;
|
||
int length = side.Cubic();
|
||
Vector3Int index = LinearToIndex(linear);
|
||
index = index.Sub(radius);
|
||
|
||
for(int i = 0; i < length; i++)
|
||
{
|
||
var neighbor = GetNeighbor(IndexToLinear(index +
|
||
LinearToGridIndex(i, side)))
|
||
.GetEnumerator();
|
||
while(neighbor.MoveNext())
|
||
{
|
||
yield return neighbor.Current;
|
||
}
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 实现
|
||
|
||
public IEnumerator<KeyValuePair<int, List<T>>> GetEnumerator()
|
||
{
|
||
foreach(var list in grid)
|
||
{
|
||
yield return list;
|
||
}
|
||
}
|
||
|
||
IEnumerator IEnumerable.GetEnumerator()
|
||
{
|
||
return GetEnumerator();
|
||
}
|
||
|
||
#endregion
|
||
}
|
||
} |