Menggambar Bintang Natal / Stellecah Dodecahedron

10

Bintang kertas adalah hal besar di keluarga saya saat natal, jadi saya pikir bintang virtual akan keren.

Di bawah ini adalah gambar dari dodecahedron biasa (dari https://en.wikipedia.org/wiki/Dodecahedron , dikaitkan dengan penulis yang disebutkan di sana.)

masukkan deskripsi gambar di sini

Proses stasi (wikipedia) ketika diterapkan pada polyhedron melibatkan perpanjangan wajah sampai mereka melintasi wajah lain. Maka dimulai dengan dodecahedron biasa, kita mendapatkan bentuk-bentuk berikut:

Dodecahedron Stellated Kecil, Dodecahedron Besar dan Dodecahedron Stellated Besar

Gambar dari http://jwilson.coe.uga.edu/emat6680fa07/thrash/asn1/stellations.html

masukkan deskripsi gambar di sini

Ini adalah tiga kemungkinan Stellations of the dodecahedron (Wolfram). Mereka membentuk perkembangan alami dari dodecahedron, ke dodecahedron bintang kecil, dodecahedron besar dan dodecahedron bintang besar, ketika kita memperluas wajah lebih jauh dan lebih jauh.

Tugas

Program atau fungsi Anda harus menampilkan atau menampilkan ke file gambar salah satu polyhedra berikut: Dodecahedron biasa, Dodecahedron bintang kecil, Great dodecahedron atau Great Stellated Dodecahedron .

Skema warna harus seperti gambar kedua di atas. Masing-masing dari enam pasang wajah yang berlawanan harus merupakan salah satu dari enam warna Merah, Kuning, Hijau, Cyan, Biru, dan Magenta. Anda dapat menggunakan warna default dengan nama-nama ini dalam bahasa Anda atau dokumentasinya, atau menggunakan warna FF0000, FFFF00, 00FF00, 00FFFF, 0000FF, dan FF00FF (Anda dapat mengurangi warna ini dengan mengurangi intensitas hingga minimum 75% jika diinginkan, misalnya dengan mengurangi nilai F ke nilai C.)

Perhatikan bahwa kita mendefinisikan "wajah" sebagai semua area di bidang yang sama. Jadi dalam gambar di atas wajah depan berwarna kuning (dan wajah belakang paralel juga akan berwarna kuning.)

Latar belakang harus hitam, abu-abu, atau putih. Tepi mungkin dihilangkan, tetapi harus hitam jika ditarik.

Aturan

Polyhedron yang ditampilkan harus memiliki lebar antara 500 dan 1000 piksel (lebar didefinisikan sebagai jarak maksimum antara dua simpul yang ditampilkan.)

Polyhedron yang ditampilkan harus dalam proyeksi perspektif (sudut pandang setidaknya 5 lebar dari polyhedron), atau proyeksi ortografi (efektif proyeksi perspektif dengan sudut pandang di infinity).

Polihedron harus dapat ditampilkan dari sudut manapun. (Tidak dapat diterima untuk memilih sudut yang paling mudah dan membuat bentuk 2D hardcode.) Sudut dapat ditentukan oleh pengguna dengan salah satu cara berikut:

  1. Input dari tiga sudut yang sesuai dengan tiga rotasi, dari stdin, atau sebagai parameter fungsi atau perintah. Ini bisa berupa sudut Euler (di mana rotasi pertama dan terakhir sekitar sumbu yang sama) atau sudut Tait-Bryan (di mana masing-masing ada satu rotasi tentang sumbu x, y dan z) https://en.wikipedia.org/ wiki / Euler_angles (sederhananya, apa pun berlangsung selama setiap rotasi adalah tentang sumbu x, y, atau z dan rotasi berturut-turut adalah sumbu tegak lurus.)

  2. Fasilitas bagi pengguna untuk memutar polyhedron dalam langkah-langkah tidak lebih dari 10 derajat tentang sumbu x dan y dan menyegarkan tampilan, setiap kali jumlah sewenang-wenang (dengan asumsi sumbu z tegak lurus terhadap layar).

Polyhedron harus solid, bukan rangka gambar.

Tidak ada bawaan untuk menggambar polyhedra diizinkan (Saya melihat Anda, Mathematica!)

Mencetak gol

Ini adalah codegolf. Kode terpendek dalam byte menang.

Bonus

Lipat gandakan skor Anda dengan 0,5 jika Anda tidak menggunakan builtin untuk menggambar 3D.

Lipat gandakan skor Anda dengan 0,7 jika Anda dapat menampilkan ketiga stellations dari dodecahedron, dapat dipilih oleh pengguna dengan integer 1-3 yang dimasukkan dari stdin, atau dengan fungsi atau parameter baris perintah.

Jika Anda memilih kedua bonus, skor Anda akan dikalikan dengan 0,5 * 0,7 = 0,35

Info berguna (sumber seperti di bawah ini)

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

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

Dodecahedron memiliki 20 simpul. 8 dari mereka membentuk simpul kubus dengan koordinat kartesius (x, y, z) berikut:

(± 1, ± 1, ± 1)

12 sisanya adalah sebagai berikut (phi adalah rasio emas)

(0, ± 1 / φ, ± φ)

(± 1 / φ, ± φ, 0)

(± φ, 0, ± 1 / φ)

Cembung lambung dodecahedron bintang kecil dan dodecahedron besar jelas merupakan dodecahedron biasa. Vertikal luar menggambarkan icosahedron.

Menurut Wikipedia, 12 simpul icosahedron dapat dideskripsikan dengan cara yang sama seperti permutasi siklik dari (0, ± 1, ± φ). Vertikal luar dari dodecaheron bintang kecil dan dodechahedron besar (pada skala yang sama dengan dodecahedron di atas) membentuk icosahedron yang lebih besar, di mana koordinat simpul adalah permutasi siklik dari (0, ± φ ^ 2, ± φ).

Sudut antara wajah untuk dodecahedron dan icosahedron masing-masing adalah 2 arctan (phi) dan arccos (- (√5) / 3).

Untuk kiat memutar, lihat https://en.wikipedia.org/wiki/Rotation_matrix

EDIT: Secara tidak sengaja saya telah mengizinkan dodecahedron biasa, dan tidak bisa menariknya sekarang. Bonus x0.7 untuk menggambar ketiga polyhedra yang dibintangi tetap. Pada Hari Tahun Baru saya akan mengeluarkan hadiah 100 untuk jawaban yang dapat menampilkan sebagian besar dari empat polyhedra, dengan kode terpendek sebagai penahan ikatan.

Level River St
sumber
@ LegionMammal978 bawaan untuk menggambar polyhedra (mis. dodecahedron) Tidak diizinkan. Beberapa bahasa memiliki fasilitas untuk membangun model 3D dengan perintah seperti triangle[[a,b,c],[p,q,r],[x,y,z]]. Bahasa-bahasa ini umumnya memiliki builtin untuk memutar dan menampilkan model, secara otomatis menjaga agar tidak menampilkan wajah yang tersembunyi, dll. Solusi seperti ini diperbolehkan tetapi tidak akan menarik bonus. Tujuan dari bonus ini adalah untuk memungkinkan bahasa yang tidak memiliki fasilitas ini menjadi kompetitif, dan juga untuk menarik solusi yang lebih menarik.
Level River St
@ LegionMammal978 haha, saya tahu Mathematica akan menjadi bahasa yang menyebabkan masalah. Polyhedrondatadilarang karena jelas merupakan builtin untuk menggambar polyhedra. Jika jawaban Anda tidak menggunakan builtin untuk menggambar polyhedra, dan mematuhi aturan lain, maka itu dapat diterima. Maksud Anda tampaknya adalah mengingat fakta bahwa Anda harus mewarnai wajah dengan benar, Polyhedrondatatoh tidak akan menyelamatkan Anda banyak, jadi dalam praktiknya mungkin menjadi pembatasan yang agak sewenang-wenang. Saya setuju sampai batas tertentu, tetapi itu lebih adil untuk semua jika saya menghindari mengubah aturan setelah memposting.
Level River St

Jawaban:

3

Python 2.7, 949 byte

Berikut adalah solusi untuk dodecahedron biasa yang diplot menggunakan matplotlib. Garis besar kasar untuk kode yang tidak diserami (tidak diperlihatkan di sini) diuraikan di bawah ini:

  • Buat simpul Buat pinggiran (berdasarkan 3 tetangga terdekat, module scipy.spatial.KDtree)
  • Buat wajah berdasarkan siklus grafik dengan panjang 5 (modul jaringanx)
  • Buat facenormals (dan pilih yang menghadap ke luar normal, numpy.cross)
  • Hasilkan pewarnaan berdasarkan normals wajah
  • Merencanakan menggunakan 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()

masukkan deskripsi gambar di sini

Willem
sumber
3

Ruby, 784 byte * 0,5 * 0,7 = 274,4

Jawaban saya sendiri, karena itu tidak memenuhi syarat untuk hadiah saya.

Memenuhi syarat untuk bonus built-in non-3D dan menggambar semua bonus stellations.

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

Input sebagai parameter fungsi

Integer 0..3 sesuai dengan dodecahedron biasa, dodecahedron bintang kecil, dodecahedron bintang besar

Array tiga bilangan bulat sesuai dengan derajat derajat untuk rotasi tentang sumbu x, y dan x (lagi) (sudut Euler yang tepat, memungkinkan rotasi apa pun yang dicapai.)

Keluarkan file p.svgyang dapat ditampilkan di browser web.

Penjelasan

array x, y, z di bagian bawah kode berisi koordinat titik-titik luar dari satu wajah dodecahedron bintang kecil. Ini dapat dituliskan dalam icosahedron yang 12 simpulnya ditentukan oleh permutasi siklik dari (+/- 377, + / - 233, + / - 0). Perhatikan bahwa 377 dan 233 adalah angka Fibonacci berturut-turut dan karenanya 377/233 merupakan perkiraan yang sangat baik untuk rasio emas.

array tambahan w berisi koordinat x dikalikan dengan -1, setara dengan refleksi di bidang x. Fungsi f disebut 6 kali, sekali untuk setiap warna, dengan permutasi siklik yang berbeda dari x, y, z dan w, y, z.

Tiga rotasi dilewatkan sebagai parameter dalam n []. untuk menggunakan sin dan cos di Ruby, perlu dilakukan include Math. untuk menghindari ini, cosinus dan sinus dari sudut diperoleh dengan menaikkan akar kuadrat dari -1 "i"ke kekuatan (sudut dalam derajat / 90) Bagian nyata dan imajiner dari angka ini disimpan dalam k (cosinus) dan l ( sinus)

Sebelum rotasi, nilai x dan y dipertukarkan. Kemudian perkalian matriks diterapkan pada nilai-nilai y dan z untuk memberikan rotasi tentang sumbu x. Pertukaran nilai memungkinkan tiga rotasi dilakukan dalam satu lingkaran.

Sejauh ini, kami hanya memiliki satu cincin poin. Untuk mendapatkan sisanya, kita perlu menemukan pusat pentagon / bintang. Ini dilakukan dengan mencari rata-rata koordinat dari 5 simpul, yang disimpan dalam p, q, r.

Seperti disebutkan sebelumnya, hanya satu panggilan fungsi per warna yang dibuat. Tanda r (rata-rata koordinat z, dan karenanya koordinat wajah) diuji. Jika positif, wajah adalah wajah depan dan karenanya terlihat. Jika negatif, wajah adalah wajah belakang. Itu tidak terlihat, dan kami tidak memiliki fungsi panggilan untuk wajah yang berlawanan. Oleh karena itu, ketiga koordinat harus dibalik. Tanda r disimpan di e untuk memfasilitasi ini.

Wajah dibangun dari 5 segitiga, yang simpulnya adalah kombinasi linear dari simpul luar dodecahedron bintang kecil dan pusat wajah. Dalam kasus dodecahedron bintang kecil, untuk ujung segitiga kita atur a = 1 dan b = 0 (kontribusi 1 dari x, y, z dan 0 dari p, q, r). Untuk 2 simpul dasar dari segitiga kita atur c = -0,382 (kontribusi 1 / rasio emas ^ 2 dari x, y, z) dan d = 1,382 (kontribusi dari p, q, r.) Alasan untuk kontribusi negatif adalah bahwa simpul-simpul dasar segitiga ditentukan berdasarkan ujung-ujung yang berlawanan, yang berada pada sisi yang berlawanan dari muka. Koordinat yang diperoleh dikalikan dengan e seperlunya.

Keempat array tanpa nama yang nilainya ditugaskan untuk a,b,c,dberisi nilai yang diperlukan untuk dodecahedron biasa, dodecahedron bintang kecil, dodecahedron besar dan dodecahedron besar, dipilih sesuai dengan variabel. tPerhatikan bahwa untuk dodecahedron bintang kecil dan dodecahedron besar, a + b = c + d = 1. Relasi a + b = c + d berlaku untuk bentuk lain, tetapi skala yang berbeda diterapkan.

Baris kode svg dibuat untuk setiap segitiga. Ini berisi ID yang berasal dari jumlah koordinat z dari 3 simpul segitiga, deskripsi simpul dari tiga koordinat segitiga, dan warna. perhatikan bahwa kita melihat lurus ke bawah sumbu z dalam proyeksi ortografis. Jadi 2D x = 3D x dan 2D y = 3D y. Baris ditambahkan keh.

Akhirnya, setelah semua pemanggilan fungsi selesai, h diurutkan sehingga segitiga dengan nilai z tertinggi (di depan) diplot terakhir, dan semuanya disimpan sebagai file svg dengan teks header dan footer yang sesuai.

Tidak digabungkan dalam program uji

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]

Keluaran

untuk dodecahedron bintang kecil (akan segera menambahkan beberapa gambar dari poligon lain)

1,0,0,0 posisi rumah

masukkan deskripsi gambar di sini

1,30,0,0 berputar ke bawah 30 derajat

masukkan deskripsi gambar di sini

1,0,30,0 putar ke kanan 30 derajat (catatan: untuk tampilan sisi yang sempurna, rotasi akan menjadi atan(1/golden ratio)= 31,7 derajat, maka kita masih bisa melihat sepotong kecil warna biru)

masukkan deskripsi gambar di sini

1,0,20,0 putar kanan 20 derajat

masukkan deskripsi gambar di sini

1,60,10, -63 putar ke bawah, kanan dan atas (contoh orientasi hanya mungkin dengan 3 putaran)

masukkan deskripsi gambar di sini

0,30,0,0 dodecahedron biasa

masukkan deskripsi gambar di sini

2,0,20,0 dodecahedron besar

masukkan deskripsi gambar di sini

3,45,45,45 dodecahedron bintang besar masukkan deskripsi gambar di sini

Level River St
sumber
3

Mathematica, 426 424 byte

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]

Menggunakan bawaan Graphics3Duntuk menampilkan bentuk. Sebagian besar byte diambil oleh lokasi titik terkompresi, namun, yang kemudian Partitiondiubah menjadi bentuk yang dapat digunakan oleh Polygon. Akhirnya:

Perhatikan bahwa bentuk ini dapat diputar dengan mengklik dan menarik.

LegionMammal978
sumber
OMG, saya akan menghapus dodecahedron biasa! Sejauh yang saya tahu (saya tidak tahu atau memiliki Mathematica) ini sesuai dengan aturan, jadi +1.
Level River St
@ Greveverrill Saya tidak berpikir itu akan mengubah ukuran terlalu banyak, tapi saya lebih suka tidak harus menulis ulang ini dari awal.
LegionMammal978
Jawaban Anda tetap valid, saya tidak akan mengubah aturan, itu akan menjadi bentuk yang buruk. Namun, selain bonus 0,7 untuk tiga polyhedra bintang, saya telah menawarkan hadiah untuk jawaban yang dapat menghasilkan sebagian besar dari empat polyhedra. Jika Anda memang memutuskan untuk memperbarui jawaban Anda, saya rasa Anda mungkin menyimpan banyak byte dengan menghasilkan koordinat secara algoritmik (lihat bagian info yang berguna dari pertanyaan itu.)
Level River St
@steveverrill, saya akan, tetapi ternyata, lokasi titik melibatkan akar quartics, dan saya tidak dapat menemukan pola.
LegionMammal978