2015-06-23 3 views
0

У меня есть массив (объект [,,]), допустим для аргументов радиус массив x1000, y1000, z * 1000 и представляет собой матрицу точек на x, y, z.C# select less 3d array from large 3d array

в положении: x50, y10, z199, например, я хочу извлечь другой объект [,,], содержащий меньший куб, скажем, подматрицу из 100 кубов (или что-то еще доступно, nulls, если пустое?) Из родительского массив, использующий контрольную точку в качестве центральной точки, это возможно, я надеялся, что смогу сделать это в linq, но потерял безнадежно. Как бы вы/я должен был заняться этим. Один из них должен был сделать следующее:

1. Создайте новый трехмерный массив с размером количества элементов, которые я хочу получить (xyz).

2.Ищите по каждой оси (x, y, z).

3.Copy значение из исходного массива в целевой массив (offsetX + x, offsetY + y, offsetZ + z).

4. Возврат нового массива.

но если это называется много, я вижу, что это довольно узкое место, идеи кто-нибудь?

ответ

1

В зависимости от использования меньшего массива это может удовлетворить ваши потребности.


Представлять подразделы (кусок) массив, вместо того чтобы создавать новый массив или делать какое-либо копирование, вы можете написать свой собственный класс, который служит видом на этот кусок массива.

Обратите внимание, что в этом примере имеет следующие свойства:

  • Нет защитных положений в конструктор
  • Кусок всегда куба (х, у, длина г равны)
  • длина Кусок всегда нечетно (поскольку мы расширяем из точки отсчета)

 

public class ArrayChunk<T> 
{ 
    // Array this chunk is from. 
    private readonly T[,,] _parentArray; 
    // Point of reference. 
    private readonly int _x, _y, _z; 
    // How many elements to move outwards in each direction from point of reference. 
    private readonly int _numToExpand; 

    public ArrayChunk(T[,,] parentArray, int x, int y, int z, int numToExpand) 
    { 
     _parentArray = parentArray; 
     _x = x; 
     _y = y; 
     _z = z;    
     _numToExpand = numToExpand; 
    } 

    public int Length => _numToExpand*2 + 1; 

    public T this[int x, int y, int z] 
    { 
     get 
     { 
      // Make sure index is within chunk range. 
      EnsureInChunkRange(x, y, z); 
      // Map chunk index to parent array index. 
      int parentX = MapToParent(_x, x), 
       parentY = MapToParent(_y, y), 
       parentZ = MapToParent(_z, z); 
      // If parent array index is in parent array range, return element from parent array. 
      if (IsInRangeOfParent(parentX, parentY, parentZ)) 
       return _parentArray[parentX, parentY, parentZ]; 
      // Otherwise return default element for type T. 
      return default(T); 
     } 
     set 
     { 
      EnsureInChunkRange(x, y, z); 
      int parentX = MapToParent(_x, x), 
       parentY = MapToParent(_y, y), 
       parentZ = MapToParent(_z, z); 
      if (IsInRangeOfParent(parentX, parentY, parentZ)) 
       _parentArray[parentX, parentY, parentZ] = value; 
      else 
       throw new InvalidOperationException(); 
     } 
    } 

    private void EnsureInChunkRange(int x, int y, int z) 
    { 
     if (x < 0 || y < 0 || z < 0 || 
      x >= Length || y >= Length || z >= Length) 
     { 
      throw new IndexOutOfRangeException(); 
     } 
    } 

    private int MapToParent(int referenceIndex, int index) 
    { 
     return referenceIndex - _numToExpand + index; 
    } 

    private bool IsInRangeOfParent(int parentX, int parentY, int parentZ) 
    { 
     return 
      parentX >= 0 && 
      parentY >= 0 && 
      parentZ >= 0 && 
      parentX < _parentArray.GetLength(0) && 
      parentY < _parentArray.GetLength(1) && 
      parentZ < _parentArray.GetLength(2); 
    }     
} 

Чтобы легко получить кусок от массива, можно объявить метод расширения:

public static class ArrayChunkExtensions 
{ 
    public static ArrayChunk<T> GetChunk<T>(this T[,,] array, int x, int y, int z, int numToExpand) 
    { 
     return new ArrayChunk<T>(array, x, y, z, numToExpand); 
    } 
} 

Вот Пример использования:

Action<int, Action<int, int, int>> iterate = (length, action) => 
{ 
    for (int x = 0; x < length; x++) 
     for (int y = 0; y < length; y++) 
      for (int z = 0; z < length; z++) 
       action(x, y, z); 
}; 

// Create 5x5x5 parent array. 

const int size = 5; 
var array = new string[size, size, size]; 
iterate(size, (x, y, z) => array[x, y, z] = $"x:{x} y:{y} z:{z}"); 

// Take 3x3x3 chunk from parent array center. 

const int indexOfReference = 2; 
const int numToExpand = 1; 
ArrayChunk<string> chunk = array.GetChunk(indexOfReference, indexOfReference, indexOfReference, numToExpand); 
iterate(chunk.Length, (x, y, z) => Console.WriteLine(chunk[x, y, z])); 
+0

Спасибо, выглядит прикосновение более эффективной, чем то, что я придумал , Я попробую и дам вам знать/отметьте как ответ –

+0

Дайте мне знать, если у вас возникнут проблемы или возникнут вопросы. –