Narysuj Gwiazdkę Bożego Narodzenia / Stellated Dodecahedron

10

Gwiazdy papierowe są ważną rzeczą w mojej rodzinie na święta, więc pomyślałem, że wirtualna będzie fajna.

Poniżej znajduje się obraz zwykłego dwunastościanu (z https://en.wikipedia.org/wiki/Dodecahedron , przypisanego autorowi wspomnianemu tam.)

wprowadź opis zdjęcia tutaj

Proces stelowania (wikipedia) po zastosowaniu do wielościanu obejmuje wydłużanie twarzy, aż przecinają inne twarze. W ten sposób zaczynając od zwykłego dwunastościanu, otrzymujemy następujące kształty:

Mały dwunastościan gwiaździsty, dwunastościan wielki i dwunastościan gwiaździsty

Zdjęcie z http://jwilson.coe.uga.edu/emat6680fa07/thrash/asn1/stellations.html

wprowadź opis zdjęcia tutaj

Są to trzy możliwe Stellacje dwunastościanu (Wolfram). Tworzą naturalną progresję od dwunastościanu do małego gwiaździstego dwunastościanu, wielkiego dwunastościanu i wielkiego dwunastościanu gwiaździstego, gdy rozszerzamy twarze coraz dalej.

Zadanie

Twój program lub funkcja powinna wyświetlać lub wyświetlać w pliku obrazu jedną z następujących wielościanów: Zwykły dwunastościan, Mały dwunastościan gwiaździsty, Wielki dwunastościan wielki lub Dwunastościan wielki .

Schemat kolorów powinien być taki jak na drugim obrazku powyżej. Każda z sześciu par przeciwległych twarzy będzie miała jeden z sześciu kolorów: czerwony, żółty, zielony, cyjan, niebieski i magenta. Możesz użyć domyślnych kolorów z tymi nazwami w swoim języku lub w dokumentacji lub użyć kolorów FF0000, FFFF00, 00FF00, 00FFFF, 0000FF i FF00FF (możesz je stonować, zmniejszając intensywność do minimum 75% w razie potrzeby, na przykład poprzez zmniejszenie F do C.)

Zauważ, że definiujemy „twarz” jako wszystkie obszary w tej samej płaszczyźnie. Zatem na zdjęciach powyżej przednia twarz jest żółta (a równoległa tylna twarz również byłaby żółta).

Tło powinno być czarne, szare lub białe. Krawędzie można pominąć, ale powinny być czarne, jeśli zostaną narysowane.

Zasady

Wyświetlany wielościan musi mieć szerokość od 500 do 1000 pikseli (szerokość jest definiowana jako maksymalna odległość między dowolnymi dwoma wyświetlanymi wierzchołkami).

Wyświetlany wielościan musi być rzutowany perspektywicznie (punkt widzenia co najmniej 5 szerokości od wielościanu) lub rzut ortograficzny (w rzeczywistości rzut perspektywiczny z punktem widzenia w nieskończoności).

Wielościan musi być możliwy do wyświetlenia pod dowolnym kątem. (Niedopuszczalne jest wybranie najłatwiejszego możliwego kąta i zrobienie zakodowanego kształtu 2D). Kąt może być określony przez użytkownika na jeden z następujących sposobów:

  1. Wprowadzanie trzech kątów odpowiadających trzem obrotom, od standardowej wartości, lub jako parametry funkcji lub wiersza poleceń. Mogą to być albo kąty Eulera (gdzie pierwszy i ostatni obrót dotyczą tej samej osi) lub kąty Tait-Bryan (gdzie każdy obrót jest wokół osi x, y i z) https://en.wikipedia.org/ wiki / Euler_angles (najprościej mówiąc, wszystko idzie tak długo, jak długo każdy obrót dotyczy osi x, y lub z, a kolejne obroty dotyczą osi prostopadłych.)

  2. Możliwość obracania wielościanu w krokach nie większych niż 10 stopni wokół osi xiy oraz odświeżania wyświetlacza dowolną liczbę razy (przy założeniu, że oś Z jest prostopadła do ekranu).

Wielościan musi być pełny, a nie szkieletowy.

Żadne wbudowane funkcje do rysowania wielościanów nie są dozwolone (patrzę na ciebie, Mathematica!)

Punktacja

To jest codegolf. Najkrótszy kod w bajtach wygrywa.

Bonusy

Pomnóż swój wynik przez 0,5, jeśli nie używasz wbudowanych narzędzi do rysowania 3D.

Pomnóż swój wynik przez 0,7, jeśli możesz wyświetlić wszystkie trzy stellacje dwunastościanu, wybierane przez użytkownika przez liczbę całkowitą 1-3 wprowadzoną ze standardowego wejścia lub przez funkcję lub parametr wiersza poleceń.

Jeśli wybierzesz oba bonusy, Twój wynik zostanie pomnożony przez 0,5 * 0,7 = 0,35

Przydatne informacje (źródła jak poniżej)

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

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

Dwunastościan ma 20 wierzchołków. 8 z nich tworzy wierzchołki sześcianu o następujących współrzędnych kartezjańskich (x, y, z):

(± 1, ± 1, ± 1)

Pozostałe 12 to: phi to złoty podział

(0, ± 1 / φ, ± φ)

(± 1 / φ, ± φ, 0)

(± φ, 0, ± 1 / φ)

Wypukły kadłub małego gwiaździstego dwunastościanu i wielkiego dwunastościanu jest oczywiście regularnym dwunastościanem. Zewnętrzne wierzchołki opisują dwudziestościan.

Według Wikipedii 12 wierzchołków dwudziestościanu można opisać w podobny sposób, jak cykliczne permutacje (0, ± 1, ± φ). Zewnętrzne wierzchołki małego gwiaździstego dwunastościanu i wielkiego dwunastościanu (w tej samej skali co dwunastościan powyżej) tworzą większy dwudziestościan, w którym współrzędne wierzchołków są cyklicznymi permutacjami (0, ± φ ^ 2, ± φ).

Kąty między ścianami dla dwunastościanu i dwudziestościanu wynoszą odpowiednio 2 arctan (phi) i arccos (- (√5) / 3).

Aby uzyskać porady dotyczące obracania, zobacz https://en.wikipedia.org/wiki/Rotation_matrix

EDYCJA: Przez pomyłkę zezwoliłem na zwykły dwunastościan i nie mogę go teraz wycofać. Premia x0,7 za narysowanie wszystkich trzech gwiaździstych wielościanów pozostaje. W Nowy Rok wydam nagrodę w wysokości 100 za odpowiedź, która może wyświetlać większość czterech wielościanów, z najkrótszym kodem jako rozstrzygnięciem remisu.

Level River St
źródło
Wbudowane @ LegionMammal978 do rysowania wielościanów (np. dodecahedron) Są niedozwolone. Niektóre języki mają możliwości budowania modeli 3D za pomocą poleceń takich jak triangle[[a,b,c],[p,q,r],[x,y,z]]. Języki te mają na ogół wbudowane funkcje obracania i wyświetlania modelu, automatycznie dbając o to, aby nie wyświetlać ukrytych twarzy itp. Takie rozwiązania są dozwolone, ale nie przyciągną premii. Celem premii jest umożliwienie konkurowania językom, które nie mają tych udogodnień, a także przyciągnięcie ciekawszych rozwiązań.
Level River St
@ LegionMammal978 haha, wiedziałem, że Mathematica będzie językiem, który powoduje problemy. Polyhedrondatajest niedozwolony, ponieważ jest wyraźnie wbudowanym narzędziem do rysowania wielościanów. Jeśli twoja odpowiedź nie używa wbudowanych funkcji do rysowania wielościanów i jest zgodna z innymi zasadami, to jest do przyjęcia. Chodzi o to, że biorąc pod uwagę fakt, że musisz odpowiednio pokolorować twarze, i tak Polyhedrondatabyś cię nie oszczędził, więc w praktyce może to być nieco arbitralne ograniczenie. Zgadzam się do pewnego stopnia, ale jest to bardziej sprawiedliwe dla wszystkich, jeśli uniknę zmiany zasad po opublikowaniu.
Level River St

Odpowiedzi:

3

Python 2.7, 949 bajtów

Oto rozwiązanie dla zwykłego dwunastościanu wykreślonego przy użyciu matplotlib. Nieprzetworzony zarys kodu niepoznanego (nie pokazanego tutaj) został przedstawiony poniżej:

  • Twórz wierzchołki Twórz krawędzie (na podstawie 3 najbliższych sąsiadów, moduł scipy.spatial.KDtree)
  • Twórz ściany na podstawie cykli grafowych o długości 5 (moduł networkx)
  • Twórz facenormale (i wybierz te z normalnym skierowaniem na zewnątrz, numpy.cross)
  • Generuj kolorystykę na podstawie normalnych twarzy
  • Rysowanie przy użyciu 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()

wprowadź opis zdjęcia tutaj

Willem
źródło
3

Rubinowy, 784 bajtów * 0,5 * 0,7 = 274,4

Moja własna odpowiedź, dlatego nie kwalifikuje się do mojej nagrody.

Kwalifikuje się zarówno do premii wbudowanej innej niż 3D, jak i premii za losowanie wszystkich gwiazd.

->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}

Wprowadź jako parametry funkcji

Liczba całkowita 0..3 odpowiadająca dwunastościanowi regularnemu, dwunastościanowi gwiaździstemu, dwunastościanowi gwiaździstemu

Tablica trzech liczb całkowitych odpowiadających kątom stopni dla obrotu wokół osi x, y i x (ponownie) (właściwe kąty Eulera, umożliwiające osiągnięcie dowolnego obrotu).

Wydrukuj plik, p.svgktóry można wyświetlić w przeglądarce internetowej.

Wyjaśnienie

tablice x, y, z na dole kodu zawierają współrzędne zewnętrznych punktów jednej powierzchni małego gwiaździstego dwunastościanu. Można to zapisać w dwudziestościanie, którego 12 wierzchołków jest określonych przez cykliczne permutacje (+/- 377, +/- 233, +/- 0). Zauważ, że 377 i 233 są kolejnymi liczbami Fibonacciego, a zatem 377/233 jest doskonałym przybliżeniem złotego stosunku.

dodatkowa tablica w zawiera współrzędne x pomnożone przez -1, co odpowiada odbiciu w płaszczyźnie x. Funkcja f jest wywoływana 6 razy, raz dla każdego koloru, z różnymi cyklicznymi permutacjami x, y, z oraz w, y, z.

Trzy obroty są przekazywane jako parametry w n []. aby użyć grzechu i cos w Ruby, trzeba to zrobić include Math. aby tego uniknąć, cosinus i sinus kąta uzyskuje się, podnosząc pierwiastek kwadratowy z -1 "i"do potęgi (kąt w stopniach / 90). Rzeczywiste i urojone części tej liczby są przechowywane w k (cosinus) i l ( sinus)

Przed obrotem wymieniane są wartości xiy. Następnie do wartości y i z stosuje się mnożenie macierzy, aby uzyskać obrót wokół osi x. Wymiana wartości umożliwia wykonanie trzech obrotów w pętli.

Do tej pory mamy tylko jeden pierścień punktów. Aby uzyskać resztę, musimy znaleźć środek pięciokąta / gwiazdy. Odbywa się to poprzez znalezienie średniej współrzędnych 5 wierzchołków, które są przechowywane w p, q, r.

Jak wspomniano wcześniej, wykonywane jest tylko jedno wywołanie funkcji na kolor. Testowany jest znak r (średnia współrzędnych z, a zatem współrzędnych twarzy). Jeśli jest pozytywna, twarz jest twarzą przednią i dlatego jest widoczna. Jeśli jest ujemny, twarz jest tylną. Jest niewidoczny i nie mamy wywołania funkcji dla przeciwnej twarzy. Dlatego wszystkie trzy współrzędne muszą zostać odwrócone. Znak r jest przechowywany w e, aby to ułatwić.

Twarz jest zbudowana z 5 trójkątów, których wierzchołki są liniowymi kombinacjami zewnętrznych wierzchołków małego gwiaździstego dwunastościanu i środka twarzy. W przypadku małego gwiaździstego dwunastościanu dla wierzchołków trójkątów ustawiamy a = 1 ib = 0 (wkład 1 z x, y, z i 0 z p, q, r). Dla 2 podstawowych wierzchołków trójkąta ustawiamy c = -0,382 (wkład 1 / złoty stosunek ^ 2 z x, y, z) id = 1,382 (wkład z p, q, r.) Przyczyną ujemnego wkładu jest że wierzchołki podstawy trójkąta są zdefiniowane w kategoriach przeciwnych końców, które znajdują się po przeciwnej stronie twarzy. Otrzymane współrzędne są w razie potrzeby mnożone przez e.

Cztery nienazwane tablice, których wartości są przypisane, aby a,b,c,dzawierały wymagane wartości dla zwykłego dwunastościanu, małego dwunastościanu gwiaździstego, wielkiego dwunastościanu i wielkiego dwunastościanu gwiaździstego, wybranych zgodnie ze zmienną. tUwaga: dla małego dwunastościanu gwiaździstego i dwunastościanu wielkiego a + b = c + d = 1. Relacja a + b = c + d dotyczy innych kształtów, ale stosowana jest inna skala.

Dla każdego trójkąta tworzona jest linia kodu svg. Zawiera identyfikator wyprowadzony z sumy współrzędnych z 3 wierzchołków trójkąta, opis wierzchołków trzech współrzędnych trójkąta i kolor. zauważ, że patrzymy prosto w dół osi Z w rzucie ortograficznym. Zatem 2D x = 3D x i 2D y = 3D y. Linia zostanie dodana doh.

na koniec, po zakończeniu wszystkich wywołań funkcji, h jest sortowane tak, że trójkąty o najwyższej wartości z (z przodu) są drukowane na końcu, a całość jest zapisywana jako plik svg z odpowiednim tekstem nagłówka i stopki.

Niegolfowany w programie testowym

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]

Wynik

dla małego gwiaździstego dwunastościanu (wkrótce doda kilka zdjęć innych wielokątów)

1,0,0,0 pozycja domowa

wprowadź opis zdjęcia tutaj

1,30,0,0 obróć o 30 stopni w dół

wprowadź opis zdjęcia tutaj

1,0,30,0 obróć w prawo o 30 stopni (uwaga: dla idealnego widoku z boku obrót wyniósłby atan(1/golden ratio)= 31,7 stopni, stąd nadal możemy zobaczyć mały kawałek niebieskiego)

wprowadź opis zdjęcia tutaj

1,0,20,0 obróć w prawo o 20 stopni

wprowadź opis zdjęcia tutaj

1,60, 10, -63 obrót w dół, w prawo i w górę (przykład orientacji możliwy tylko przy 3 obrotach)

wprowadź opis zdjęcia tutaj

0,30,0,0 dwunastościan regularny

wprowadź opis zdjęcia tutaj

2,0,20,0 wielki dwunastościan

wprowadź opis zdjęcia tutaj

3,45,45,45 wielki gwiaździsty dwunastościan wprowadź opis zdjęcia tutaj

Level River St
źródło
3

Mathematica, 426 424 bajtów

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]

Używa wbudowanego Graphics3Ddo wyświetlania kształtu. Większość bajtów jest jednak zajmowana przez skompresowane lokalizacje wierzchołków, które są następnie Partitionprzekształcane do postaci możliwej do użycia przez Polygon. Wreszcie:

Pamiętaj, że ten kształt można obracać, klikając i przeciągając.

LegionMammal978
źródło
OMG, zamierzałem usunąć zwykły dwunastościan! O ile mogę powiedzieć (nie znam ani nie mam Matematyki), jest to zgodne z zasadami, więc +1.
Level River St
@steveverrill Nie sądzę, żeby to zbytnio zmieniło rozmiar, ale wolałbym nie pisać od nowa.
LegionMammal978
Twoja odpowiedź pozostaje aktualna, nie zamierzam zmieniać zasad, to byłaby zła forma. Jednak oprócz premii 0,7 za trzy gwiaździste wielościany, zaoferowałem nagrodę za odpowiedź, która może wytworzyć większość z czterech wielościanów. Jeśli zdecydowałeś się zaktualizować swoją odpowiedź, myślę, że możesz zaoszczędzić wiele bajtów, generując algorytmy algorytmicznie (patrz przydatna część informacji w pytaniu).
Level River St
@steveverrill, chciałbym, ale najwyraźniej lokalizacje wierzchołków dotyczą korzeni kwartyki i nie mogę znaleźć wzoru.
LegionMammal978