Повернуть гиперкуб

27

Введение

Гиперкуб / тессеракт - это 4-мерный эквивалент нормального куба. Это делается путем взятия сетки кубов, расширения ее до 3-го измерения, а затем - с использованием 4-го измерения - складывания в гиперкуб. Это в основном куб, где каждая сторона - куб.

Для создания гиперкуба вам нужно 16 4d векторов (вектор с an x, a y, a zи wкомпонентом). Эти векторы следующие:

A(0, 0, 0, 0); B(1, 0, 0, 0); C(1, 0, 1, 0); D(0, 0, 1, 0); E(0, 1, 0, 0); F(1, 1, 0, 0); G(1, 1, 1, 0); H(0, 1, 1, 0); 
I(0, 0, 0, 1); J(1, 0, 0, 1); K(1, 0, 1, 1); L(0, 0, 1, 1); M(0, 1, 0, 1); N(1, 1, 0, 1); O(1, 1, 1, 1); P(0, 1, 1, 1);

Гиперкуб имеет 24 лица. Следующий список содержит их все (каждая группа помечена квадратом):

ABFE, CDHG, BCGF, DAEH, DCBA, FEHG
IJNM, KLPO, JKON, LIMP, LKJI, PMNO
ABJI, DCKL, BCKJ, DAIL, FEMN, GHPO, FGON, EHPM, EAIM, BFNJ, CGOK, HDLP

Со всей этой информацией у вас технически есть гиперкуб в коде. Чтобы повернуть это, вам нужно 6 различных матриц для каждой плоскости вращения, по одной для плоскостей YZ, XZ, XY, XW, YW и ZW. После того, как у вас есть каждая матрица, вам нужно умножить вершины куба на них.

Следующие изображения показывают структуру каждой матрицы:

Для вращения на плоскости YZ:

Для вращения на плоскости XZ:

Для вращения на плоскости XY:

Для вращения на плоскости XW:

Для вращения на плоскости YW:

Для вращения на плоскости ZW:

Вращения применяются в этом порядке.

После всего этого у вас есть повернутый гиперкуб. Теперь вам нужно нарисовать это. Вы должны использовать ортогональную проекцию в сочетании с перспективной проекцией , чтобы отправить (x, y, z, w)в (2x/(2+z), 2y/(2+z)).

вход

Вы вводите 6 целых чисел от 0 (включительно) до 360 (исключительно). Они представляют повороты в градусах на разных плоскостях вращения гиперкуба.

Выход

Ваш вывод должен быть одним изображением, содержащим гиперкуб. Дисплей может быть растровым изображением, векторным изображением или ASCII-изображением. Выходное изображение должно быть не менее 100 * 100 пикселей, а куб должен занимать не менее 50% экрана. Разрешен любой формат вывода изображения по умолчанию.

Контрольные примеры

0 0 0 0 0 0

0 0 0 0 0 30

30 0 0 0 0 30

0 0 0 30 30 30

45 45 45 0 0 0

45 45 45 45 45 45

Откройте изображения в новой вкладке, чтобы увидеть их в полном размере.

правила

  • Применяются правила по умолчанию
  • Стандартные лазейки запрещены
  • Самый короткий код в байтах выигрывает
Балинт
источник
Почему вы взорвали другой пост?
Rɪᴋᴇʀ
@ EᴀsᴛᴇʀʟʏIʀᴋ Я отправил это в чат для последнего обзора
Bálint
7
Как я уже два раза отмечал в песочнице, описание проекции для отображения неполно, поскольку предполагает, что проецируемый объект является трехмерным, тогда как на самом деле он, очевидно, четырехмерный.
Питер Тейлор
2
@luserdroog Я думаю, что «U» должно быть «N».
стакан
2
@ Bálint Спасибо за вызов, мне понравилось. Надеюсь, мы получим больше ответов и разных подходов. : D
стакан

Ответы:

9

Октава, 474 433 429 байт

function H(a,b,c,d,e,f) C=@cosd;S=@sind;R=[1,0,0,0;0,C(e),0,-S(e);0,-S(e)*S(f),C(f),-C(e)*S(f);0,S(e)*C(f),S(f),C(e)*C(f)]*[C(c)*C(d),-S(c)*C(d),0,S(d);S(c),C(c),0,0;0,0,1,0;-C(c)*S(d),S(c)*S(d),0,C(d)]*[C(b),S(a)*S(b),C(a)*S(b),0;0,C(a),-S(a),0;-S(b),S(a)*C(b),C(a)*C(b),0;0,0,0,1]*(dec2bin(0:15)'-48.5);Z=R(3,:)+2;R=2*R./Z;Q=[1,2,10,12,11,9,10,14,16,12,4,8,16,15,11,3,7,15,13,9,1,5,13,14,6,8,7,5,6,2,4,3,1];plot(R(1,Q),R(2,Q));

повернутый:

function H(a,b,c,d,e,f) 
C=@cosd;S=@sind;
R=[1,0,0,0;0,C(e),0,-S(e);0,-S(e)*S(f),C(f),-C(e)*S(f);0,S(e)*C(f),S(f),C(e)*C(f)]*
  [C(c)*C(d),-S(c)*C(d),0,S(d);S(c),C(c),0,0;0,0,1,0;-C(c)*S(d),S(c)*S(d),0,C(d)]*
  [C(b),S(a)*S(b),C(a)*S(b),0;0,C(a),-S(a),0;-S(b),S(a)*C(b),C(a)*C(b),0;0,0,0,1]*
  (dec2bin(0:15)'-48.5);
Z=R(3,:)+2;
R=2*R./Z;
Q=[1,2,10,12,11,9,10,14,16,12,4,8,16,15,11,3,7,15,13,9,1,5,13,14,6,8,7,5,6,2,4,3,1];
plot(R(1,Q),R(2,Q));

Матрицы вращения по-прежнему занимают много байтов, но цикл Эйлера сработал довольно хорошо, сократив число посещенных вершин с 96 120 до 33.

Вершины генерируются, принимая 4-битное двоичное представление [0:15]и рассматривая msb как x-координату, а lsb w-координату.

Изменить: Предварительное умножение всех матриц вращения было кошмаром, поэтому я не использовал его изначально, но предварительное умножение их в парах сэкономило 41 байт. Теперь искать оптимальную комбинацию. :) Умножение матриц на три было хуже, чем отсутствие предварительного умножения, поэтому я буду счастлив с парным подходом.


Выход:

H(0,0,0,0,0,0)

Н (0,0,0,0,0,0)

H(0,0,0,0,0,30)

Н (0,0,0,0,0,30)

H(30,0,0,0,0,30)

Н (30,0,0,0,0,30)

H(0,0,0,30,30,30)

Н (0,0,0,30,30,30)

H(45,45,45,0,0,0)

Н (45,45,45,0,0,0)

H(45,45,45,45,45,45)

Н (45,45,45,45,45,45)

мерный стакан
источник
Редактировать: я тупой одурачен одной и той же переменной повсюду ... [Вы уверены, что вам не нужна полная предварительно умноженная матрица? :) i.imgur.com/nkM6y6g.png]
algmyr
@algmyr Да, полностью умноженная матрица получилась вдвое длиннее, если я правильно помню.
мензурка
Это должно быть больше похоже на это, наслаждайтесь глупыми «упрощениями» Максимы
algmyr
Чтобы восполнить неудачу в математике, вот более удачная версия вашего кода, 330 байтов: paste.ee/p/2GRyJ
algmyr
14

постскриптум 1075 732 683 640 631 601 590 545 542 526 514 478 470

Использует mat.ps и G .

Редактировать: -343 Прикладная двоичная кодировка генерации векторов и эйлерова схемакраденыхзаимствовано из других ответов. И применил строки двоичных токенов из библиотеки G.
Изменить: -49 Переопределено sin cosи negдля более коротких имен.
Изменить: -43 Определены короткие имена для последовательностей 0 0 0 1 1 0.
Изменить: -9 al (т.е. aload) короче, чем (")@. Факторинг 3 звонка idi(т.е. idiv) за счет ничего не делать 1 idiv.
Редактировать: -30 Применяется блок неявного определения из G.
Редактировать: -10 Еще несколько трижды используемых последовательностей.
Редактировать: -45 Удалить переменные i j k l m nдля углов и всегда определять текущий угол как переменную. Отложить выполнение кода-описания матрицы вращения до егоt функции углов используют значение (глобальное)ttзначение готово.
Редактировать: -3 Удалить <16>$т.е. closepath, И пространство.
Редактировать: -16 скобок массива фактора из векторов единиц в матрицах вращения ( J K Lи M). Повторно подать заявку упал moза modи suза sub.
Edit: -12 В-Выложи проект-и-начертить функцию и удалить (теперь пустой) ограждающий словарь.
Редактировать: -36 Кодировать схему (т.е. грани ) в строку.
Редактировать: -8 Удалить определение массива вершинV . Вместо этого оставьте на стеке иdupрабочие копии по мере необходимости (один раз, сначала и снова в конце цикла). Кроме того, переведено несколько операторов из строк двоичных токенов обратно в сокращенные имена, где BTS не дала сбережений, (I)$как и сейчас fora(т.е. forall). if duможет быть (T8)$, но if duэто явно лучший выбор (это гольф , а не запутывание как таковое). Кроме того, выполните scale до translate , так что переведенные координаты могут быть 3и 4вместо 300и 400.

(mat.ps)run 3(G)run $
t sin
A neg
t cos
0 0
0 1
1 0
2 mu Z 2(!V)@
idi 2 mo .5 su
(>8)$
[F D]
[D E]
[E D]
[D F]

3 4 100(&>88)$(,)# div(<N)#[E 15{[I 1 H I 2 H I 4 H ex 8 H]}fo]E
5{ARGUMENTS 1(XK/)$/t ex d{{J[0 C B 0][0 A C 0]K}{[C 0 A 0]L[B 0
C 0]K}{[C B D][A C D]M K}{[C D A]L M[B D C]}{J[0 C 0 B]M[0 A 0
C]}{J L[D C B][D A C]}}(>K)$[(>?)$]transpose matmul}fo
du(019;:89=?;37?>:26><804<=576451320){48 su get al po{W
Z Y X}{(>3)$}fora X G Y G{li}(D)#{mov}if du}fora(HB)#

Символы 3 4и 100в первой строке второго блока представляют собой параметры, представляющие соответственно центр-х, центр-у и масштаб чертежа на странице (координаты центра масштабируются с помощью scale). (300 400) - примерно центр американской бумаги размером с букву (612 792) в единицах PS.

Если вы можете приблизительно следовать postScript, важными причудливыми вещами являются неявный блок процедур и закодированные строки операторов. Как показано в комментариях к рабочему файлу ниже, каждая строка первого блока неявно именуется A, B, C и т. Д. Так, например, F E Dбудет производить 1 0 0 1 0 0. Для закодированных строк операторов - все, что является аргументом $ #или @является последовательностью вызовов операторов, используя байты для выбора операторов из таблицы системных имен, PLRM 3ed, Приложение F. Эти и другие функции доступны для PostScript с библиотекой G ( теперь включает в себя функции mat.ps).

Рабочий файл:

(mat.ps)run 3(G)run $
t sin %/A
A neg %/B
t cos %/C
0 0 %/D
0 1 %/E
1 0 %/F
2 mu Z 2(!V)@ %/G  %ad div %add div %108 1 54
idi 2 mo .5 su %idiv mod sub %/H %106 169 51
(>8)$ %/I %exch dup
[F D] %/J
[D E] %/K
[E D] %/L
[D F] %/M


3 4
100(&>88)$ %currentlinewidth exch dup dup %38
(,)#  %scale %139-95=44
div(<N)# %div setlinewidth %54 155-95=60 %translate %173-95=78
%/V
[E 15{[ I
    1 H I
    2 H I
    4 H ex
    8 H]}fo]

E 5{ARGUMENTS 1(XK/)$ %index get cvr %88 75 47
    /t ex d %exch def %62 51
    {{J[0 C B 0][0 A C 0]K} 
     {[C 0 A 0]L[B 0 C 0]K} 
     {[C B D][A C D]M K} 
     {[C D A]L M[B D C]}
     {J[0 C 0 B]M[0 A 0 C]}
     {J L[D C B][D A C]}}
    (>K)$ %exch get %62 75
    [
        (>?)$ %exch exec %62 63
    ]
    transpose matmul
}fo %for
du %dup
%d %def
%{transpose matmul}fora d

%[E 9 11 10 8 9 13 15 11 3 7 15 14 10 2 6 14 12 8 0 4 12 13 5 7 6 4 5 1 3 2 0]
%<0001090b0a08090d0f0b03070f0e0a02060e0c0800040c0d050706040501030200>
%          abcdef
%0123456789:;<=>?
(019;:89=?;37?>:26><804<=576451320)
{48 su get % 169 75 %V (>K)$ %sub %exch get

    al po %aload pop %2 117
    {W Z Y X}{(>3)$ %exch def
    }fora %forall %2 117  62 51 73
    X G
    Y G
    {li}(D)# %stopped
    {mov}
    if du%(T8)$ %if %84 du %dup 56
}
%<49a7a1>$ %forall stroke showpage %73 167-95=72 161-95=66
fora(HB)#

Неутомимый и слегка прокомментированный:

300 400 translate   %roughly center of letter paper
currentlinewidth
100 dup dup scale
div setlinewidth    %scale x100, reduce line-width/100
(mat.ps)run         %load matrix library
ARGUMENTS aload pop{f e d c b a}{exch cvr def}forall  %define args as 
                                 % a,b,etc and convert to real numbers
/m{2 mod .5 sub}def
/P{aload pop{w z y x}{exch def}forall   %P: [x y z w]  project-and-draw  -
    x 2 mul z 2 add div 
    y 2 mul z 2 add div 
    {lineto}stopped{moveto}if %catch(&handle!) nocurrentpoint error in lineto
}bind def
/V[0 1 15{    % generate vectors with a for-loop
    [ exch
        dup m
        1 index 2 idiv m
        2 index 4 idiv m
        4 3 roll 8 idiv m
    ]
}for]
[[[1 0 0 0][0 a cos a sin neg 0][0 a sin a cos 0][0 0 0 1]] 
     [[b cos 0 b sin 0][0 1 0 0][b sin neg 0 b cos 0][0 0 0 1]] 
     [[c cos c sin neg 0 0][c sin c cos 0 0][0 0 1 0][0 0 0 1]] 
     [[d cos 0 0 d sin][0 1 0 0][0 0 1 0][d sin neg 0 0 d cos]]
     [[1 0 0 0][0 e cos 0 e sin neg][0 0 1 0][0 e sin 0 e cos]]
     [[1 0 0 0][0 1 0 0][0 0 f cos f sin neg][0 0 f sin f cos]]]
{transpose matmul} forall def   % apply array of rotations and define

%Eulerian circuit (borrowed and adjusted for 0-based indexing)
[0 1 9 11 10 8 9 13 15 11 3 7 15 14 10 2 6 14 12 8 0 4 12 13 5 7 6 4 5 1 3 2 0]

% the main program!
% on the stack is the Eulerian circuit array
{
    V exch get  %lookup index in (sextuply-transformed) vertex array
    P           %call project-and-draw
} forall
closepath stroke %draw it, don't just think about it

showpage % gs's cmd-line-args option automatically sets -dBATCH,
    % so without a showpage, gs will immediately exit before you
    % can look at the picture :(

Некоторые из моих выводов являются зеркальным отображением примеров вопроса.

Ибо gs -- hc.ps 0 0 0 0 0 0я получаю:
введите описание изображения здесь

gs -- hc.ps 0 0 0 0 0 30
введите описание изображения здесь

gs -- hc.ps 30 0 0 0 0 30
введите описание изображения здесь

gs -- hc.ps 0 0 0 30 30 30
введите описание изображения здесь

gs -- hc.ps 45 45 45 0 0 0
введите описание изображения здесь

gs -- hc.ps 45 45 45 45 45 45
введите описание изображения здесь

Бонусную анимацию я только что сделал с помощью этой программы. Это изображение соответствует последовательности вращения 0 30 60 0 i i , где i варьируется от 0 до 360 на 2.
введите описание изображения здесь

Люзер Дрог
источник
2
Вау. Ответ PostScript для математической задачи.
TuxCrafting
@ TùxCräftîñg На самом деле в этом вопросе не так много математики, если вы можете легко выполнять матричное умножение. И я хотел написать эту программу с тех пор, как прочитал « The Armchair Universe» А. К. Дьюдни .
luser droog
Добавлены новые функции в библиотеку G. Не могу использовать здесь, но это позволяет эту 307-байтовую версию .
luser droog
8

C # + Unity, 1060 845 835 байт

C # - Java

Предполагается, что эта функция находится в сценарии MainCamera.

Редактировать:
Спасибо @TuukkaX за предложения по сохранению 19 байт. Сохранено ~ 200 байт с использованием цикла Эйлера.

Golfed:

void d(float[]r){transform.position=Vector3.back*2;GetComponent<Camera>().backgroundColor=Color.black;Vector4[]p=new Vector4[16];Matrix4x4[]m=new Matrix4x4[6];int i=0;for(;i<16;i++)p[i]=new Vector4(i%2,i/2%2,i/4%2,i/8%2)-new Vector4(.5f,.5f,.5f,.5f);int[,]X={{6,8,1,12,7,11},{5,0,0,0,5,10},{10,10,5,15,15,15}};for(i=0;i<6;i++){m[i]=Matrix4x4.identity;r[i]=Mathf.Deg2Rad*r[i];float c=Mathf.Cos(r[i]),s=Mathf.Sin(r[i]);m[i][X[1,i]]=c;m[i][X[2,i]]=c;m[i][X[0,i]]=s;m[i][X[0,i]%4*4+X[0,i]/4]=-s;}for(i=0;i<16;i++)foreach(Matrix4x4 x in m)p[i]=x*p[i];int[]F={0,1,9,11,10,8,9,13,15,11,3,7,15,14,10,2,6,14,12,8,0,4,12,13,5,7,6,4,5,1,3,2,0};LineRenderer l=new GameObject().AddComponent<LineRenderer>();l.SetVertexCount(33);l.material=new Material(Shader.Find("Sprites/Default"));l.SetWidth(.03f,.03f);for(i=0;i<33;i++)l.SetPosition(i,p[F[i]]);

Новые строки + отступы + Полная оболочка:

using UnityEngine;
using System.Collections;

public class h : MonoBehaviour {

    void d(float[]r)
    {
        transform.position=Vector3.back*2.5f;
        GetComponent<Camera>().backgroundColor=Color.black;
        Vector4[]p=new Vector4[16];
        Matrix4x4[]m=new Matrix4x4[6];
        int i=0;
        for(;i<16;i++)p[i]=new Vector4(i%2,i/2%2,i/4%2,i/8%2)-new Vector4(.5f,.5f,.5f,.5f);
        int[,]X={{6,8,1,12,7,11},{5,0,0,0,5,10},{10,10,5,15,15,15}};
        for (i=0;i<6;i++){
            m[i]=Matrix4x4.identity;
            r[i]=Mathf.Deg2Rad*r[i];
            float c=Mathf.Cos(r[i]);
            float s=Mathf.Sin(r[i]);
            m[i][X[1,i]]=c;
            m[i][X[2,i]]=c;
            m[i][X[0,i]]=s;
            m[i][X[0,i]%4*4+X[0,i]/4]=-s;
        }
        for (i=0;i<16;i++)foreach(Matrix4x4 x in m)p[i]=x*p[i];
        int[]F={0,1,9,11,10,8,9,13,15,11,3,7,15,14,10,2,6,14,12,8,0,4,12,13,5,7,6,4,5,1,3,2,0};
        LineRenderer l=new GameObject().AddComponent<LineRenderer>();
        l.SetVertexCount(33);
        l.material=new Material(Shader.Find("Sprites/Default"));
        l.SetWidth(.03f,.03f);
        for (i=0;i<33;i++)
            l.SetPosition(i,p[F[i]]);
        l.gameObject.tag = "Player";
    }
    public float[] input;
    void Start()
    {
        d(input);
    }
}

Я не мог найти простую формулу для построения матриц вращения или «граней» для рисования, так что это стоило бы много байтов для жесткого кода. Я позаимствовал цикл Эйлера у @beaker. Кроме того, встроенные модули Unity чрезвычайно многословны.

Вы можете проверить все тестовые случаи онлайн .

синий
источник
Это первый раз, когда я увидел ответ C # + Unity здесь. +1
DanTheMan
Я думаю, что каждый 0.5fможет быть уменьшен до .5fи 0.01fдо .01f. Я также думаю, что целочисленные массивы могут быть разделены запятой вместо того, чтобы говорить int[]несколько раз.
Yytsi
@ Синий О, ты прав! Некоторое время не пользовался C #, поэтому не был уверен в последнем совете.
Yytsi
@TuukkaX Проигнорируйте мой предыдущий комментарий, я могу использовать int[,]. Тем не менее, спасибо.
Синий,
У вас все еще есть, Vector4(0.5f,0.5f,0.5f,0.5f)который может быть уменьшен до Vector4(.5f,.5f,.5f,.5f).
Yytsi
6

Javascript ES6, 584 байта

f=(...R)=>(P=s=>[...s].map(i=>parseInt(i,16)),C=document.createElement`canvas`,X=C.getContext`2d`,X.translate((C.width=300)/2,(C.height=300)/2),X.lineWidth=0.01,X.scale(100,100),X.beginPath(),P("0267fd9804c8ab915dcefb37546ea2310").map((e,i)=>{[x,y,z]=P("084c2a6e195d3b7f").map(i=>[...(1e3+i.toString(2)).slice(-4)].map(i=>i-0.5)).map(e=>(R.map((R,i,_,M=Math,C=M.cos(r=R*M.PI/180),S=M.sin(r))=>((a,b,s=1)=>[e[a],e[b]]=[C*e[a]-s*S*e[b],s*S*e[a]+C*e[b]])(...[[1,2],[0,2,-1],[0,1],[0,3,-1],[1,3],[2,3]][i])),e))[e];[x,y]=[2*x/(2+z),2*y/(2+z)];i?X.lineTo(x,y):X.moveTo(x,y)}),X.stroke(),C)

"Ungolfed":

f=(...R)=>(                                                              // function that accepts rotations in the following form: f(a,b,c,d,e,f)
    P=s=>[...s].map(i=>parseInt(i,16)),                                  // function to convert strings to hex-arrays
    V=P("084c2a6e195d3b7f")                                              // vertices encoded as hex values ( [0,1,1,0] -> 6 )
        .map(i=>[...(1e3+i.toString(2)).slice(-4)].map(i=>i-0.5))        // convert hex values to vertices, center the hypercube
        .map(e=>(R.map((R,i,_,M=Math,C=M.cos(r=R*M.PI/180),S=M.sin(r))=> // convert angles to degrees, precalculate sin and cos values
        ((a,b,s=1)=>[e[a],e[b]]=[C*e[a]-s*S*e[b],s*S*e[a]+C*e[b]])       // apply matrix transforms to all vertices
        (...[[1,2],[0,2,-1],[0,1],[0,3,-1],[1,3],[2,3]][i])),e)),        // list of encoded matrix transforms
    C=document.createElement`canvas`,X=C.getContext`2d`,                 // create image to draw on
    X.translate((C.width=300)/2,(C.height=300)/2),                       // setup image dimensions, center transform
    X.lineWidth=0.01,X.scale(100,100),X.beginPath(),                     // setup line, scale the transform and begin drawing
    P("0267fd9804c8ab915dcefb37546ea2310").map((e,i)=>{                  // hypercube edge path indices encoded as hex values
        [x,y,z]=V[e];[x,y]=[2*x/(2+z),2*y/(2+z)];                        // project vertex
        i?X.lineTo(x,y):X.moveTo(x,y)}),X.stroke(),                      // draw vertex
    C)                                                                   // return image

Посмотрите это в действии (изменено, чтобы непрерывно вращаться):

with(document)with(Math)with(document.getElementById`canvas`)with(getContext`2d`){render=()=>{requestAnimationFrame(render);clearRect(0,0,width,height);save();K=performance.now();R=[K*0.01,K*0.02,K*0.03,K*0.04,K*0.05,K*0.06];X=s=>[...s].map(i=>parseInt(i,16));V=X("084c2a6e195d3b7f").map(i=>[...(1e3+i.toString(2)).slice(-4)].map(i=>i-0.5)).map(e=>(R.map((R,i,_,C=cos(r=R*PI/180),S=sin(r))=>((a,b,s=1)=>[e[a],e[b]]=[C*e[a]-s*S*e[b],s*S*e[a]+C*e[b]])(...[[1,2],[0,2,-1],[0,1],[0,3,-1],[1,3],[2,3]][i])),e));translate((width=300)/2,(height=300)/2);lineWidth=0.01;scale(100,100);beginPath();X("0267fd9804c8ab915dcefb37546ea2310").map((e,i)=>{[x,y,z]=V[e];[x,y]=[2*x/(2+z),2*y/(2+z)];i?lineTo(x,y):moveTo(x,y)});stroke();restore();};render();}
<html><body><canvas id="canvas"></canvas></body></html>

Функция возвращает объект холста HTML5, вам нужно добавить его на страницу, document.body.appendChild(f(0,0,0,0,0,0))например.

В настоящее время повороты применяются не по порядку, я работаю над переупорядочением, но, как есть, он вращает гиперкуб правильно.

Dendrobium
источник
Умно, мне потребовалось некоторое время, чтобы понять, что вы делаете с матричными преобразованиями. : D Кроме того, я не могу заставить твой фрагмент кода работать ... это дает мне бесполезную "Ошибка сценария". в строке 0.
стакан
@beaker Какой браузер вы используете? Я проверил это на последнем Firefox.
Дендробиум
Я на Safari 9.1.1. Позвольте мне попробовать другой.
стакан
1
Да, Chrome работает просто отлично.
стакан
1
Сафари это дерьмо. Не используйте его, чтобы проверить, работает ли что-то.
Патрик Робертс
1

Mathematica, 453 415 байт *

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

Graphics[Line[Table[{2#/(2+#3),2#2/(2+#3)}&@@Map[Dot@@Table[Table[If[n==m==#2||n==m==#,Cos[#3],If[n==#2&&m==#,If[#2==1&&(#==3||#==4),1,-1]Sin[#3],If[n==#&&m==#2,If[#2==1&&(#==3||#==4),-1,1]Sin[#3],If[n==m,1,0]]]],{n,4},{m,4}]&[k[[1]],k[[2]],a[[k[[3]]]]°],{k,{{4,3,6},{4,2,5},{4,1,4},{2,1,3},{3,1,2},{3,2,1}}}].#&,Tuples[{0,1},4]-.5,{1}][[i]],{i,{1,2,10,12,11,9,10,14,16,12,4,8,16,15,11,3,7,15,13,9,1,5,13,14,6,8,7,5,6,2,4,3,1}}]]]

* Я подсчитывать °и ==как одиночные байты каждый , так как они представлены в виде одного символа в системе Mathematica. Я думаю, что это справедливо, так как многие языки используют странные кодировки символов.

Разгулялся с комментариями. Ввод жестко закодирован вверху как a={30,0,0,0,0,30};. Я не считал это к моему счету.


a = {45, 45, 45, 45, 45, 45};



(* #2,#-th rotation matrix as a funciton of #3 *)
(* Using the \
#-notation saved 6 bytes over the more common function definition \
notation*)
r = 
  Table[If[n == m == #2 || n == m == #, Cos[#3], 
     If[n == #2 && m == #, 
      If[#2 == 1 && (# == 3 || # == 4), 1, -1] Sin[#3], 
      If[n == # && m == #2, 
       If[#2 == 1 && (# == 3 || # == 4), -1, 1] Sin[#3], 
       If[n == m, 1, 0]]]], {n, 4}, {m, 4}] &;

(* Total rotation matrix. Need six of them. Function of the six \
angles to rotate.*)

u = Dot @@ 
     Table[r[k[[1]], 
       k[[2]], \[Degree]*
        a[[k[[3]]]]], {k, {{4, 3, 6}, {4, 2, 5}, {4, 1, 4}, {2, 1, 
         3}, {3, 1, 2}, {3, 2, 1}}}].# &;



(* List of all vertices of the hypercube *)
t = Tuples[{0, 1}, 4];
t -= .5;
v = Map[u, t, {1}];

(*projection*)
p = {2 #/(2 + #3), 2 #2/(2 + #3)} &;

(*Eulerian tour*)

l = Table[
   p @@ v[[i]], {i, {1, 2, 10, 12, 11, 9, 10, 14, 16, 12, 4, 8, 16, 
     15, 11, 3, 7, 15, 13, 9, 1, 5, 13, 14, 6, 8, 7, 5, 6, 2, 4, 3, 
     1}}];
Graphics[Line[l]]

0 0 0 0 0 30

0 0 0 30 30 30

введите описание изображения здесь

405 10 -14 -8 -9 205

введите описание изображения здесь

dylnan
источник