Насколько мне известно, не существует значительно более умного способа сделать это.Эта проблема часто возникает во всех видах обработки изображений, но обычно вам приходится допускать различные виды обработки границ (« - это граница неопределенная / нулевая / зеркальная / повторная / идентичная ближайшему пикселю / и т. Д.? *)1002 * ").
Обычный подход заключается в работе с массивом, который был увеличен на 1 в каждом направлении (т. Е. +2 в каждом измерении), при этом значения границ установлены правильно.Тогда вы гарантированно не выйдете за границы массива (если вы правильно поняли индексы цикла), но сначала вам нужно выделить новый массив.
В зависимости от того, как часто вам придется делать этовзаимодействия, в качестве альтернативы может быть полезно написать функцию, которая возвращает массив из семи соседних значений, заданных координатами центрального пикселя, и выполняет правильную обработку границ (например, NaN для вокселей вне вашего массива):
std::array<float, 7> getVoxelAndNeighbors(int x, int y, int z)
Это делает ваш код наиболее читабельным в конце, но аспект производительности может немного пострадать, потому что вы должны выполнять проверку границ для каждого элемента, даже если только очень немногие действительно нуждаются в этом.
Другая возможность можетобрабатывать поверхности (и края (и углы)) отдельно от «общего» тела цикла:
for (z = 1; z < SIZE-1; ++z)
for (y = 1; y < SIZE-1; ++y)
for (x = 1; x < SIZE-1; ++x)
{ /* Your original body */ }
for (y = 1; y < SIZE-1; ++y)
for (x = 1; x < SIZE-1; ++x)
{ /* Handle positive and negative z surface */ }
// (Repeat for x, y)
for (x = 1; x < SIZE-1; ++x)
{ /* Handle edges in x direction */ }
// (Repeat for x, y)
// Handle all eight corners.
Это лучше для производительности в отношении неправильных предсказаний ветвления (нет if
s в циклетело), но это еще более многословно для записи и гораздо хуже с точки зрения согласованности кэша.