Намалюйте різдвяну зірку / зоряний додекаедр


10

Паперові зірки - це велика річ у моїй родині на Різдво, тому я думав, що віртуальна буде крутою.

Нижче зображено звичайний додекаедрhttps://en.wikipedia.org/wiki/Dodecahedron , приписаний автору, згаданому там).

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

Процес стелляції (вікіпедія) при застосуванні до багатогранника передбачає розширення граней, поки вони не перетинають інші грані. Таким чином, починаючи зі звичайного додекаедра, ми отримуємо такі форми:

Малий зоряний додекаедр, великий додекаедр і великий зоряний додекаедр

Зображення з http://jwilson.coe.uga.edu/emat6680fa07/thrash/asn1/stellations.html

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

Це три можливі зірки додекаедра (Вольфрам). Вони утворюють природний прогрес від додекаедра, до малого зоряного додекаедра, великого додекаедра і великого зоряного додекаедра, оскільки ми розширюємо грані все далі і далі.

Завдання

Ваша програма або функція повинна відображати або виводити у файл зображення одне з таких многогранників: Регулярний додекаедр, Малий зоряний додекаедр, Великий додекаедр або Великий зоряний додекаедр .

Колірна гамма повинна бути як друге зображення вище. Кожна з шести пар протилежних граней має бути одним із шести кольорів Червоного, Жовтого, Зеленого, Блакитного, Синього та Пурпурного. Ви можете використовувати кольори за замовчуванням з цими назвами у вашій мові чи його документації або використовувати кольори FF0000, FFFF00, 00FF00, 00FFFF, 0000FF та FF00FF (ви можете зменшити їх, зменшивши інтенсивність до мінімум 75%, якщо потрібно, наприклад, зменшивши значення F до C.)

Зауважте, що ми визначаємо "обличчя" як усі області в одній площині. Таким чином, на зображеннях, розташованих над передньою поверхнею, жовтий колір (а паралельна задня поверхня також буде жовтою.

Фон повинен бути чорним, сірим або білим. Краї можуть бути опущені, але повинні бути чорними, якщо намальовані.

Правила

Відображений багатогранник повинен бути шириною від 500 до 1000 пікселів (ширина визначається як максимальна відстань між будь-якими двома відображеними вершинами.)

Відображений багатогранник повинен бути в перспективній проекції (точка зору не менше 5 ширин від багатогранника) або ортографічна проекція (фактично перспективна проекція з точки зору в нескінченність).

Багатогранник повинен бути показаний з будь-якого кута. (Неприйнятно вибирати найпростіший можливий кут і робити твердо кодовану 2D форму.) Кут може бути визначений користувачем будь-яким із наступних способів:

  1. Введення трьох кутів, що відповідають трьом обертам, від stdin, або як параметри функції або командного рядка. Це можуть бути або кути Ейлера (де перше і останнє обертання мають приблизно однакову вісь), або кути Тейт-Брайана (де є одне обертання навколо осі x, y та z) https://en.wikipedia.org/ wiki / Euler_angles (простіше кажучи, все триває так довго, що кожне обертання стосується осі x, y або z, а послідовні обертання - приблизно перпендикулярні осі.)

  2. Користувач може обертати багатогранник з кроком не більше 10 градусів навколо осей x і y та оновлювати дисплей у будь-якому довільному кількості разів (якщо вважати вісь z перпендикулярна екрану).

Багатогранник повинен бути суцільним, а не каркасною.

Не дозволяється будувати багатогранники (я дивлюся на вас, Mathematica!)

Оцінка балів

Це кодегольф. Виграє найкоротший код у байтах.

Бонуси

Помножте бал на 0,5, якщо ви не використовуєте вбудовані для 3D-малювання.

Помножте свій бал на 0,7, якщо ви зможете відобразити всі три зірки додекаедра, обрані користувачем цілим числом 1-3, введеним з stdin, або за параметром функції або командного рядка.

Якщо ви обидва бонуси, ваш рахунок буде помножений на 0,5 * 0,7 = 0,35

Корисна інформація (джерела як нижче)

https://en.wikipedia.org/wiki/Regular_dodecahedron

https://en.wikipedia.org/wiki/Regular_icosahedron

Додекаедр має 20 вершин. 8 з них утворюють вершини куба з такими декартовими (x, y, z) координатами:

(± 1, ± 1, ± 1)

Решта 12 наступні (фі - золоте співвідношення)

(0, ± 1 / φ, ± φ)

(± 1 / φ, ± φ, 0)

(± φ, 0, ± 1 / φ)

Опуклий корпус малого зоряного додекаедра та великого додекаедра, очевидно, є правильним додекаедром. Зовнішні вершини описують ікосаедр.

Згідно з Вікіпедією, 12 вершин ікосаедра можна описати аналогічно циклічним перестановкам (0, ± 1, ± φ). Зовнішні вершини малого зірчастого додекагерона та великого додехеедра (у тому ж масштабі, що й додекаедр вище) утворюють більший ікосаедр, де координати вершин є циклічними перестановками (0, ± φ ^ 2, ± φ).

Кути між гранями для додекаедра та ікосаедра дорівнюють 2 арктану (фі) та арккосу (- (√5) / 3) відповідно.

Щоб отримати поради щодо обертання, див. Https://en.wikipedia.org/wiki/Rotation_matrix

EDIT: Помилково я допустив звичайний додекаедр, і не можу його відкликати зараз. Бонус x0.7 за малювання всіх трьох зоряних багатогранників залишається. У новорічний день я видам суму в розмірі 100 за відповідь, яка може відображати більшість із чотирьох багатогранників, з найкоротшим кодом як розривом краватки.


@ LegionMammal978 вбудовані для малювання багатогранників (наприклад dodecahedron) заборонені. Деякі мови мають засоби для побудови 3D-моделей з такими командами triangle[[a,b,c],[p,q,r],[x,y,z]]. Ці мови, як правило, мають вбудовані пристрої для обертання та відображення моделі, автоматично піклуючись про не відображення прихованих облич тощо. Такі рішення дозволяються, але бонус не залучає. Мета бонусу - дозволити мовам, які не мають цих засобів, бути конкурентоспроможними, а також залучити більш цікаві рішення.
Рівень Св.

@ LegionMammal978 ха-ха, я знав, що математика буде мовою, яка спричинить проблеми. Polyhedrondataзаборонено, оскільки це очевидно вбудований малюнок багатогранників. Якщо у вашій відповіді не використовуються вбудовані для малювання багатогранників, а вони відповідають іншим правилам, то це прийнятно. Здається, ваш погляд на те, що зважаючи на те, що ви повинні правильно розфарбувати обличчя, все Polyhedrondataодно це не заощадить, тому на практиці це може бути дещо довільним обмеженням. Я згоден у такій мірі, але це справедливіше для всіх, якщо я уникаю зміни правил після публікації.
Рівень р. Св.

Відповіді:


3

Python 2.7, 949 байт

Ось рішення для звичайного додекаедра, побудованого за допомогою matplotlib. Приблизний контур для неозореного коду (не показаний тут) був викладений нижче:

  • Створення вершин Зробіть ребра (на основі 3 найближчих сусідів, модуль scipy.spatial.KDtree)
  • Створіть грані на основі циклів графіків довжиною 5 (модуль networkx)
  • Створіть обличчя (і виберіть ті, у кого зовні виходить нормальний, numpy.cross)
  • Створіть фарбування на основі норм обличчя
  • Складання графіку за допомогою matplotlib
import itertools as it
import numpy as np
from mpl_toolkits.mplot3d.art3d import Poly3DCollection
import matplotlib.pyplot as plt
v=[p for p in it.product((-1,1),(-1,1),(-1,1))]
g=.5+.5*5**.5
v.extend([p for p in it.product((0,),(-1/g,1/g),(-g,g))])
v.extend([p for p in it.product((-1/g,1/g),(-g,g),(0,))])
v.extend([p for p in it.product((-g,g),(0,),(-1/g,1/g))])
v=np.array(v)
g=[[12,14,5,9,1],[12,1,17,16,0],[12,0,8,4,14],[4,18,19,5,14],[4,8,10,6,18],[5,19,7,11,9],[7,15,13,3,11],[7,19,18,6,15],[6,10,2,13,15],[13,2,16,17,3],[3,17,1,9,11],[16,2,10,8,0]]
a=[2,1,0,3,4,5,0,1,2,3,4,5]
fig = plt.figure()
ax = fig.add_subplot((111),aspect='equal',projection='3d')
ax.set_xlim3d(-2, 2)
ax.set_ylim3d(-2, 2)
ax.set_zlim3d(-2, 2)
for f in range(12):
 c=Poly3DCollection([[tuple(y) for y in v[g[f],:]]], linewidths=1, alpha=1)
 c.set_facecolor([(0,0,1),(0,1,0),(0,1,1),(1,0,0),(1,0,1),(1,1,0)][a[f]])
 ax.add_collection3d(c)
ax.auto_scale_xyz
plt.show()

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


3

Ruby, 784 байт * 0,5 * 0,7 = 274,4

Моя відповідь, отже, не підходить для моєї винагороди.

Придатний як бонус, не вбудований у 3D, так і бонус за усіма зірками.

->t,n{o=[]
g=->a{a.reduce(:+)/5}
f=->u,v,w,m{x=u.dup;y=v.dup;z=w.dup
15.times{|i|k,l=("i".to_c**(n[i/5]/90.0)).rect
j=i%5
x[j],y[j],z[j]=y[j],x[j]*k+z[j]*l,z[j]*k-x[j]*l}
p=g[x];q=g[y];r=g[z]
a=[0,1,-i=0.382,-1][t]*e=r<=>0
b=[j=1+i,0,j,j][t]*e
c=[-i*j,-i,1,i][t]*e
d=[j*j,j,0,0][t]*e
5.times{|i|o<<"<path id=\"#{"%9.0f"%(z[i]*a+r*b+(z[i-2]+z[i-3])*c+2*r*d+999)}\"
d=\"M#{(x[i]*a+p*b)} #{(y[i]*a+q*b)}L#{(x[i-2]*c+p*d)} #{(y[i-2]*c+q*d)}L#{(x[i-3]*c+p*d)} #{(y[i-3]*c+q*d)}\"
fill=\"##{m}\"/>"}}
a=233
b=377
z=[0,a,b,a,0]
y=[a,b,0,-b,-a]
x=[b,0,-a,0,b]
w=[-b,0,a,0,-b]
f[x,y,z,'F0F']
f[w,y,z,'0F0']
f[y,z,x,'00F']
f[y,z,w,'FF0']
f[z,x,y,'F00']
f[z,w,y,'0FF']
s=File.open("p.svg","w")
s.puts'<svg xmlns="http://www.w3.org/2000/svg" viewBox="-450 -450 900 900">',o.sort,'</svg>'
s.close}

Введення як функціональних параметрів

Ціле число 0..3, відповідне правильному додекаедра, малий зоряний додекаедр, великий зоряний додекаедр

Масив з трьох цілих чисел, що відповідають градусним кутам для обертання навколо осей x, y та x (знову) (правильні кути Ейлера, що дозволяє досягти будь-якого обертання.)

Виведіть файл, p.svgякий можна відобразити у веб-браузері.

Пояснення

масиви x, y, z внизу коду містять координати зовнішніх точок однієї грані невеликого зоряного додекаедра. Це може бути вписано в ікосаедр, 12 вершин якого визначено циклічними перестановками (+/- 377, + / - 233, + / - 0). Зауважимо, що 377 і 233 - це послідовні числа Фібоначчі, і тому 377/233 є відмінним наближенням до відношення золота.

додатковий масив w містить x координати, помножені на -1, еквівалентні відображенню в площині x. Функція f називається 6 разів, один раз для кожного кольору, з різними циклічними перестановками x, y, z і w, y, z.

Три обертання передаються як параметри в n []. щоб використовувати гріх і cos в Рубі, потрібно це зробити include Math. щоб уникнути цього, косинус і синус кута отримують шляхом підняття квадратного кореня на -1"i" до сили (кут у градусах / 90) Реальні та уявні частини цього числа зберігаються у k (косинус) та l ( синус)

Перед обертанням обмінюються значення x і y. Потім матричне множення застосовується до значень y і z, щоб отримати обертання навколо осі x. Обмін значеннями дозволяє три обертання здійснюватись у циклі.

Поки ми маємо лише одне кільце точок. Для отримання решти нам потрібно знайти центр п’ятикутника / зірки. Це робиться шляхом знаходження середнього значення координат 5 вершин, які зберігаються в p, q, r.

Як було сказано раніше, робиться лише один функціональний дзвінок на колір. Перевіряється знак r (середнє значення z координат z, а отже, і координата грані). Якщо вона позитивна, обличчя переднє обличчя і тому видиме. Якщо вона негативна, обличчя - це спина. Це невидимо, і у нас немає функції виклику протилежного обличчя. Тому всі три координати повинні бути перевернуті. Знак r зберігається в e для полегшення цього.

Обличчя побудовано з 5 трикутників, вершини яких є лінійними поєднаннями зовнішніх вершин малого зоряного додекаедра та центру грані. У випадку малого зірчастого додекаедра для кінчиків трикутників встановимо a = 1 і b = 0 (внесок 1 з x, y, z та 0 з p, q, r). Для 2-х базових вершин трикутника встановимо c = -0,382 (внесок 1 / золоте співвідношення ^ 2 від x, y, z) і d = 1,338 (внесок з p, q, r.) Причиною негативного внеску є що основні вершини трикутника визначаються через протилежні кінчики, що знаходяться на протилежній стороні грані. Отримані координати множимо на е, якщо потрібно.

Чотири безіменних масиви, значення яких призначаються таким чином, щоб a,b,c,dмістити необхідні значення для звичайного додекаедра, малого зірчастого додекаедра, великого додекаедра та великого зоряного додекаедра, обраного відповідно до змінної. tЗауважте, що для малого зоряного додекаедра та великого додекаедр a a b = c + d = 1. Співвідношення a + b = c + d стосується інших фігур, але застосовується інша шкала.

Рядок коду svg створюється для кожного трикутника. Він містить ідентифікатор, отриманий із суми z координат трьох вершин трикутника, опису вершин трьох координат трикутника та кольору. зауважимо, що ми дивимось прямо вниз по осі z в ортографічній проекції. Таким чином, 2D x = 3D x і 2D y = 3D y. Рядок додано доh.

нарешті, після завершення всіх викликів функцій h сортується таким чином, щоб трикутники з найвищим значенням z (спереду) були побудовані останньою, а вся справа зберігається у вигляді файлу svg з відповідним текстом заголовка та нижнього колонтитулу.

Ungolfed в тестовій програмі

h=->t,n{                                              #t=type of polygon,n=angles of rotation
o=[]                                                  #array for output
g=->a{a.reduce(:+)/5}                                 #auxiliary function for finding average of 5 points

f=->u,v,w,m{x=u.dup;y=v.dup;z=w.dup                   #function to take 5 points u,v,w and plot one face (5 triangles) of the output in colour m 

  15.times{|i|                                        #for each of 3 rotation angle and 5 points
    k,l=("i".to_c**(n[i/5]/90.0)).rect                #calculate the cos and sine of the angle, by raising sqrt(-1)="i" to a power
    j=i%5                                             #for each of the 5 points
    x[j],y[j],z[j]=y[j],x[j]*k+z[j]*l,z[j]*k-x[j]*l}  #swap x and y, then perform maxtrix rotation on (new) y and z.

  p=g[x];q=g[y];r=g[z]                                #find centre p,q,r of the face whose 5 points (in the case of small stellated dodecahedron) are in x,y,z

  e=r<=>0                                             #if r is positive, face is front. if negative, face is back, so we need to transform it to opposite face.
  a=[0,              1,    -0.382,    -1][t]*e        #contribution of 5 points x,y,z to triangle tip vertex coordinates
  b=[1.382,          0,     1.382,     1.382][t]*e    #contribution of centre p,q,r to triangle tip vertex coordinates
  c=[-0.528,        -0.382, 1,         0.382][t]*e    #contribution of 5 points x,y,z to coordinates of each triangle base vertex 
  d=[1.901,          1.382, 0,         0][t]*e        #contribution of centre p,q,r to coordinates of each triangle base vertex

  5.times{|i|
  o<<"<path id=\"#{"%9.0f"%(z[i]*a+r*b+(z[i-2]+z[i-3])*c+2*r*d+999)}\"
d=\"M#{(x[i]*a+p*b)} #{(y[i]*a+q*b)}L#{(x[i-2]*c+p*d)} #{(y[i-2]*c+q*d)}L#{(x[i-3]*c+p*d)} #{(y[i-3]*c+q*d)}\"
fill=\"##{m}\"/>"}                                    #write svg code for this triangle 
}

  a=233                                               #a,b =coordinate standard values 
  b=377
  z=[0,a,b,a,0]                                       #z coordinates for one face of stellated dodecahedron 
  y=[a,b,0,-b,-a]                                     #y coordinates
  x=[b,0,-a,0,b]                                      #x coordinates
  w=[-b,0,a,0,-b]                                     #alternate  x coordinates

  f[x,y,z,'F0F']                                      #call f
  f[w,y,z,'0F0']                                      #to plot
  f[y,z,x,'00F']                                      #each
  f[y,z,w,'FF0']                                      #face
  f[z,x,y,'F00']                                      #in
  f[z,w,y,'0FF']                                      #turn

  s=File.open("p.svg","w")                            #sort output in o, plot front triangles last
  s.puts'<svg xmlns="http://www.w3.org/2000/svg" viewBox="-450 -450 900 900">',o.sort,'</svg>'
  s.close                                             #add header and footer, and save as svg
}

t=gets.to_i
n=[]
3.times{n<<gets.to_i}
h[t,n]

Вихідні дані

для невеликого зоряного додекаедра (незабаром додадуть зображення інших полігонів)

1,0,0,0 домашня позиція

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

1,30,0,0 обертаються вниз на 30 градусів

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

1,0,30,0 обертати на 30 градусів праворуч (зауважте: для ідеального виду збоку обертання було б atan(1/golden ratio)= 31,7 градусів, отже, ми все ще можемо побачити невеликий ковз синього кольору)

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

1,0,20,0 обертаються вправо на 20 градусів

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

1,60,10, -63 повернути вниз, вправо і вгору (приклад орієнтації можливий лише при 3 обертах)

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

0,30,0,0 звичайний додекаедр

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

2,0,20,0 чудовий додекаедр

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

3,45,45,45 чудовий зоряний додекаедр введіть тут опис зображення


3

Математика, 426 424 байт

Graphics3D[{Red,Yellow,Green,Cyan,Blue,Magenta}~Riffle~(a=Partition)[Polygon/@Uncompress@"1:eJxtkjEKwkAURNeoySYgeAVP4QFsrcTGTiyUBcEith7A2wgKgpVH8/vgs2TYZmAyw9/5k784XDbHVwihnxisU39N9SiEdI8GO/uWHpXBtjFAgJ7HToFl5WabEdJ+anCqDb6dU9RP65NR59EnI0CZDAWYjFmomBmPCn3/hVVwc9s4xYd66wYqFJVvhMz75vWlHIkhG2HBDJ1V3kYps7z7jG6GomIu/QUJKTGkdtlX2pDM8m6pydyzHIOElBhyG6V9cxulzPldaVJ6lpuUkKUTzWcm+0obkrn0f3OT0rMc0jDkD37nlUo="~a~3~a~5,2],Boxed->1<0]

Використовує вбудований Graphics3Dдля відображення форми. Однак більшість байтів займають стислі місця вершин, які потім Partitionперетворюються у форму, яку можна використовувати Polygon. Нарешті:

Зауважте, що цю форму можна обертати натисканням та перетягуванням.


OMG, я збирався видалити звичайний додекаедр! Наскільки я можу сказати (я не знаю чи маю Mathematica) це відповідає правилам, тому +1.
Рівень р. Св.

@steveverrill Я не думаю, що це занадто сильно змінить розмір, але я вважаю за краще не переписувати це з нуля.
LegionMammal978

Ваша відповідь залишається вірною, я не збираюся змінювати правила, це було б поганою формою. Однак, на додаток до бонусу 0,7 за три зоряні багатогранники, я запропонував щедрості за відповідь, яка може отримати найбільше з чотирьох багатогранників. Якщо ви все-таки вирішили оновити свою відповідь, я вважаю, що ви можете зберегти багато байтів, алгоритмічно генеруючи координати (див. Розділ корисної інформації в питанні.)
Level River St

@steveverrill, я б, але, мабуть, розташування вершин залучає коріння квартиків, і я не можу знайти шаблон.
LegionMammal978
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.