Перестановка данных для квадродерева / октодерева

Я работаю над реализацией воксельного октодерева Raycaster, и единственное, что осталось, - это переупорядочить данные для заполнения конечного уровня октодерева, чтобы затем данные можно было усреднить для построения нижних уровней дерева.

Я изначально думаю в 2D (квадродерево) для удобства. У меня данные упорядочены, как показано слева на чертеже, и в настоящее время я могу переставить их, как справа. Пример - 8x8.

Текущий

Однако я понял, что мне нужно упорядочить данные в порядке узлов, как на рисунке ниже:

Разыскивается

Другими словами, я хочу перейти от массива, где данные соответствуют таким индексам:

[0  1  2  3  4  5  6  7  8  9 ... 63]

в массив, который будет иметь данные в следующем порядке:

[0  1  4  5  16 17 20 21 2  3 ... 63]

для примера 8x8 квадродерева.

Я не могу понять, как это сделать. Моя основная проблема связана с произвольным размером дерева. Я, вероятно, мог бы жестко закодировать набор вложенных циклов, если бы заранее знал размер, но это явно не лучшее или элегантное решение. Я думаю, что есть рекурсивный способ добиться этого.

Это мой быстрый и грязный набросок для сортировки данных способом, описанным на рисунке 1. Он в основном работает, отслеживая четыре позиции в исходных данных, а затем продвигая их вперед по мере заполнения нового массива. Насколько я могу судить, это работает нормально, но не подходит для моих нужд:

 int w = 8; 
  int[] before = new int[w*w*w];
  int[] after = new int[w*w*w];
  for (int i=0; i<w*w*w; i++) {
    before[i] = i;
  }
  int toFill = 0;
  int front = 0;
  int back = w;
  int frontZ = w*w;
  int backZ = w*w + w;
  do {
   for (int i=0; i<w/2; i++) {
      for (int j=0; j<w/2; j++) {   
        after[toFill++] = front++;
        after[toFill++] = front++;
        after[toFill++] = back++;
        after[toFill++] = back++;

        after[toFill++] = frontZ++; 
        after[toFill++] = frontZ++; 
        after[toFill++] = backZ++;
        after[toFill++] = backZ++;
      }    
      front += w;
      back += w;
      frontZ += w;
      backZ += w;
    }
    front += w*w;
    back += w*w;
    frontZ += w*w;
    backZ += w*w;
  } while (toFill < w*w*w);
  for (int i=0; i<w*w*w; i++) {
    println("after " + i + " " + after[i]);
  }

person Victor Sand    schedule 26.03.2013    source источник
comment
Покажи нам, что ты пробовал.   -  person Jim Mischel    schedule 27.03.2013
comment
Похоже на кривую Z-порядка (en.wikipedia.org/wiki/Z-order_curve), что имеет смысл, учитывая, что вы говорите о деревьях quad / oct. Тем не менее, я не уверен, о чем вы спрашиваете.   -  person phs    schedule 27.03.2013
comment
Добавлено то, что я пробовал, и некоторые дополнительные пояснения. Это определенно похоже на кривую Z-порядка! Я также думаю, что было бы проще создать дерево прокси, пройти по нему и использовать этот порядок для заполнения новой структуры.   -  person Victor Sand    schedule 27.03.2013


Ответы (1)


Что касается проблемы, о которой я говорил, phs намекнул мне, что это называется кривой Z-порядка. Благодаря этому я нашел этот вопрос: Координаты кривой Z-порядка, где алгоритм для Представлен 2D кейс. Я попробовал, и все работает.

Вот несколько реализаций трехмерного случая: Как вычислить трехмерное число Мортона (чередовать биты трех целых чисел)

person Victor Sand    schedule 10.04.2013