我正在寻找C#.NET中三维循环缓冲区的实现,它允许我提取缓冲区的切片。
我尝试了多维数组,但它不允许我获取缓冲区的特定切片。
我还尝试使用锯齿状数组实现一个版本,但我发现在理解如何初始化矩阵以及切片提取方面存在一些问题。
感谢您的帮助。
[编辑1] 缓冲区将用于存储来自reltime传感器的数据,它将以宽度高度固定,深度(时间为圆形部分)将由用户定义。
我需要的切片是固定大小的矩阵(宽度和高度与给定时间的数据)。
[编辑2] 我可以实现的唯一实现。随着锯齿状阵列我仍然坚持声明(我觉得它很混乱)
public class CircularBufferMatrix<T>
{
private readonly T[,,] _buffer;
public CircularBufferMatrix(int width, int height, int depth)
{
Width = width;
Height = height;
Depth = depth;
_buffer = new T[width, height, depth];
}
public T this[int x, int y, int z]
{
set { _buffer[x, y, z%Depth] = value; }
get { return _buffer[x, y, z%Depth]; }
}
#region Getters
public int Width { get; }
public int Height { get; }
public int Depth { get; }
#endregion
}
答案 0 :(得分:1)
我会将这些分为两类。你想要一个类似CircularBuffer类的东西,它处理读写。另一个可能是您要存储的2D数组的实现。拆分这些的原因是因为你想分别读/写帧。
例如:
循环缓冲区实现:
public class CircularBuffer<T>
{
private T[] _buffer;
private int IncRollover(int value)
{
value++;
if (value >= _buffer.Length)
value = 0;
return value;
}
public CircularBuffer(int count)
{
_buffer = new T[count];
}
public bool Write(T element)
{
// if the writeindex (after increasing) equals the readindex, the buffer is full
var newWriteIndex = IncRollover(WriteIndex);
if (newWriteIndex == ReadIndex)
return false;
_buffer[WriteIndex] = element;
WriteIndex = newWriteIndex;
return true;
}
public bool TryRead(out T element)
{
if (ReadIndex == WriteIndex)
{
element = default(T);
return false;
}
element = _buffer[ReadIndex];
ReadIndex = IncRollover(ReadIndex);
return true;
}
public IEnumerable<T> ReadAll()
{
T element;
while (TryRead(out element))
yield return element;
}
public int ReadIndex { get; private set; }
public int WriteIndex { get; private set; }
}
这将负责读取和写入有效的“帧”/切片。如果您想阅读索引,可以扩展此课程。
注意:如果缓冲区已满,写入将返回false
这可能是存储在循环缓冲区中的2d缓冲区的实现:
public class MyWhateverBuffer<T>
{
private CircularBuffer<T[,]> _buffer;
public int Width { get; private set; }
public int Height { get; private set; }
public int Depth { get; private set; }
public MyWhateverBuffer(int width, int height, int depth)
{
Width = width;
Height = height;
Depth = depth;
_buffer = new CircularBuffer<T[,]>(depth);
}
public T[,] New()
{
return new T[Width, Height];
}
public bool Add(T[,] buffer)
{
return _buffer.Write(buffer);
}
public bool TryRead(out T[,] buffer)
{
return _buffer.TryRead(out buffer);
}
public IEnumerable<T[,]> ReadAll()
{
return _buffer.ReadAll();
}
}
这个类可以像:
一样使用MyWhateverBuffer<double> myBuffer = new MyWhateverBuffer<double>(100, 100, 100);
var oneSlice = myBuffer.New();
oneSlice[10, 10] = 3.5;
oneSlice[50, 10] = 23.5;
oneSlice[10, 20] = 43.5;
myBuffer.Add(oneSlice);
var anotherSlice = myBuffer.New();
anotherSlice[10, 10] = 13.5;
anotherSlice[50, 10] = 23.5;
anotherSlice[10, 20] = 43.5;
var result = myBuffer.Add(anotherSlice);
if(!result)
{
// the buffer was full..
}
// Read the results from the buffer.
foreach(var slice in myBuffer.ReadAll())
{
Trace.WriteLine(slice[10, 10]);
}
您应该始终检查是否可以添加缓冲区。你不想丢失信息。
旁注:
使用循环缓冲区获得的利润最多的是声明元素。像大数组一样,每次都会重复使用。
答案 1 :(得分:0)
如果我正确理解您的要求,您需要一个循环缓冲区,该缓冲区由二维数据数组组成,而其他项中的数据永远不会重复。 C#没有cicular缓冲区类型,但您可以自己创建一个: -
public class CircularBuffer <T> // make it generic
{
public class Iterator
{
public void MoveForward ();
public void MoveBackward ();
public T Item { get { } };
CicrcularBuffer <T> m_container;
LinkedListNode <T> m_current_item;
}
public void Add (T item);
public Iterator GetIterator ();
LinkedList<T> m_data;
}
然后创建一个包含数据的类: -
public class SensorData
{
// contains the two dimension data
}
并使用它: -
var buffer = new CircularBuffer <SensorData> ();
var iterator = buffer.GetIterator ();
var item = iterator.Item;
iterator.MoveForward ();
显然,有很多东西需要填写,但它应该让你开始。