Алгоритм генерации трехмерной кривой заполнения пространства Гильберта в Python
Я хотел бы отобразить точки в цветном кубе RGB в одномерный список в Python таким образом, чтобы список цветов выглядел красиво и непрерывно.
Я считаю, что использование трехмерной кривой заполнения Гильберта было бы хорошим способом сделать это, но я искал и не нашел очень полезных ресурсов для этой проблемы. В частности, в Википедии приведен только пример кода для создания 2D кривых.
3 ответа
Эта статья, кажется, имеет довольно дискуссию: перечень трехмерных кривых заполнения пространства Гильберта.
Цитирую из аннотации:
Двумерная кривая заполнения пространства Гильберта ценится за ее хорошие свойства локальности для многих приложений. Однако неясно, каков наилучший способ обобщить эту кривую для заполнения многомерных пространств. Мы утверждаем, что свойства, которые делают кривую Гильберта уникальной в двух измерениях, совместно используются 10694807 структурно различными кривыми заполнения пространства в трех измерениях.
Я сталкивался с вашим вопросом, пытаясь сделать то же самое в JavaScript. Я понял это самостоятельно. Вот рекурсивная функция, которая разбивает куб на 8 частей и вращает каждую часть так, чтобы она проходила по кривой Гильберта по порядку. Аргументы представляют размер:s, location:xyz и 3 вектора для повернутых осей куба. В примере вызова используется куб 256^3 и предполагается, что красный, зеленый и синий массивы имеют длину 256^3.
Должно быть легко адаптировать этот код к питону или другим процедурным языкам.
Адаптировано из фотографий здесь: http://www.math.uwaterloo.ca/~wgilbert/Research/HilbertCurve/HilbertCurve.html
function hilbertC(s, x, y, z, dx, dy, dz, dx2, dy2, dz2, dx3, dy3, dz3)
{
if(s==1)
{
red[m] = x;
green[m] = y;
blue[m] = z;
m++;
}
else
{
s/=2;
if(dx<0) x-=s*dx;
if(dy<0) y-=s*dy;
if(dz<0) z-=s*dz;
if(dx2<0) x-=s*dx2;
if(dy2<0) y-=s*dy2;
if(dz2<0) z-=s*dz2;
if(dx3<0) x-=s*dx3;
if(dy3<0) y-=s*dy3;
if(dz3<0) z-=s*dz3;
hilbertC(s, x, y, z, dx2, dy2, dz2, dx3, dy3, dz3, dx, dy, dz);
hilbertC(s, x+s*dx, y+s*dy, z+s*dz, dx3, dy3, dz3, dx, dy, dz, dx2, dy2, dz2);
hilbertC(s, x+s*dx+s*dx2, y+s*dy+s*dy2, z+s*dz+s*dz2, dx3, dy3, dz3, dx, dy, dz, dx2, dy2, dz2);
hilbertC(s, x+s*dx2, y+s*dy2, z+s*dz2, -dx, -dy, -dz, -dx2, -dy2, -dz2, dx3, dy3, dz3);
hilbertC(s, x+s*dx2+s*dx3, y+s*dy2+s*dy3, z+s*dz2+s*dz3, -dx, -dy, -dz, -dx2, -dy2, -dz2, dx3, dy3, dz3);
hilbertC(s, x+s*dx+s*dx2+s*dx3, y+s*dy+s*dy2+s*dy3, z+s*dz+s*dz2+s*dz3, -dx3, -dy3, -dz3, dx, dy, dz, -dx2, -dy2, -dz2);
hilbertC(s, x+s*dx+s*dx3, y+s*dy+s*dy3, z+s*dz+s*dz3, -dx3, -dy3, -dz3, dx, dy, dz, -dx2, -dy2, -dz2);
hilbertC(s, x+s*dx3, y+s*dy3, z+s*dz3, dx2, dy2, dz2, -dx3, -dy3, -dz3, -dx, -dy, -dz);
}
}
m=0;
hilbertC(256,0,0,0,1,0,0,0,1,0,0,0,1);
То, что часто используется в инженерной практике, - это не строго кривые Гильберта (Пеано) - это код Мортона.
https://en.wikipedia.org/wiki/Z-order_curve
Гораздо проще вычислить.