Bir Noel Yıldızı Çiz / Dodecahedron


10

Kağıt yıldızları Noel'de ailemde büyük bir şey, bu yüzden sanal bir serin olacağını düşündüm.

Aşağıda düzenli bir dodecahedron görüntüsü ( https://en.wikipedia.org/wiki/Dodecahedron'dan , burada adı geçen yazara atfedilen)

resim açıklamasını buraya girin

İşlem stellation çok yüzeyli uygulanmış (wikipedia) diğer yüzü geçene kadar yüzleri uzanan içerir. Böylece düzenli dodecahedron ile başlayarak, aşağıdaki şekilleri elde ederiz:

Küçük Stellated Dodecahedron, Büyük Dodecahedron ve Great Stellated Dodecahedron

Http://jwilson.coe.uga.edu/emat6680fa07/thrash/asn1/stellations.html adresinden resim

resim açıklamasını buraya girin

Bunlar dodekahedronun üç olası Stellasyonudur (Wolfram). Yüzleri daha da ileriye doğru genişlettikçe, dodekahedrondan küçük yıldızlanmış dodekahedrona, büyük dodekahedron ve büyük yıldızlanmış dodekahedrona doğal bir ilerleme sağlarlar.

Görev

Programınız veya işleviniz aşağıdaki polihedradan birini bir görüntü dosyasına göstermeli veya çıktı vermelidir: Düzenli dodekahedron, Küçük yıldızlı dodekahedron, Büyük dodekahedron veya Büyük Stellated Dodecahedron .

Renk şeması yukarıdaki ikinci resim gibi olmalıdır. Altı çift karşılıklı yüzün her biri altı renkten biri olan Kırmızı, Sarı, Yeşil, Camgöbeği, Mavi ve Macenta renklerinden biri olacaktır. Bu adları kendi dilinizde veya belgelerinde varsayılan renkler veya FF0000, FFFF00, 00FF00, 00FFFF, 0000FF ve FF00FF renklerini kullanabilirsiniz (istenirse yoğunluğu en az% 75'e kadar azaltarak, örneğin F'leri C'lere indirgeyerek.)

Bir "yüzü" aynı düzlemdeki tüm alanlar olarak tanımladığımızı unutmayın. Böylece, ön yüzün üstündeki görüntülerde sarıdır (ve paralel arka yüz de sarı olacaktır.)

Arka plan siyah, gri veya beyaz olmalıdır. Kenarlar atlanabilir, ancak çizilirse siyah olmalıdır.

kurallar

Görüntülenen çokyüzlünün genişliği 500 ile 1000 piksel arasında olmalıdır (genişlik, görüntülenen iki köşe arasındaki maksimum mesafe olarak tanımlanır.)

Görüntülenen çokyüzlünün perspektif projeksiyonu (polihedrondan en az 5 genişlikte bakış açısı) veya ortografik projeksiyon (sonsuza kadar bakış açısı ile etkili bir perspektif projeksiyonu) olması gerekir.

Çokyüzlünün her açıdan görüntülenebilir olması gerekir. (Mümkün olan en kolay açıyı seçmek ve sabit kodlu bir 2D şekil oluşturmak kabul edilemez.) Açı, kullanıcı tarafından aşağıdaki yollardan biriyle belirtilebilir:

  1. Stdin'den veya fonksiyon veya komut satırı parametreleri olarak üç dönüşe karşılık gelen üç açının girilmesi. Bunlar ya Euler açıları (ilk ve son rotasyonların aynı eksende olduğu yerlerde) veya Tait-Bryan açıları (x, y ve z ekseni etrafında her biri bir dönüş olduğunda) https://en.wikipedia.org/ wiki / Euler_angles (basitçe söylemek gerekirse, her dönüş x, y veya z ekseni ve ardışık dönüşler yaklaşık dikey eksenler olduğu sürece her şey devam eder.)

  2. Kullanıcının çokyüzlüyü x ve y eksenleri hakkında 10 dereceden fazla olmayan adımlarla döndürme ve ekranı, herhangi bir keyfi sayıda (z ekseninin ekrana dik olduğu varsayılarak) yenileme olanağı.

Çokyüzlünün tel çerçeve değil katı olması gerekir.

Polihedra çizmek için hiçbir yapıya izin verilmez (Sana bakıyorum Mathematica!)

puanlama

Bu kodgolf. Bayt cinsinden en kısa kod kazanır.

Bonuslar

3D çizim için builtins kullanmıyorsanız puanınızı 0,5 ile çarpın.

Kullanıcı tarafından stdin'den girilen 1-3 tamsayısı veya işlev veya komut satırı parametresi ile seçilebilen dodecahedron yıldızlarının üçünü de görüntüleyebiliyorsanız puanınızı 0,7 ile çarpın.

Her iki bonus için de giderseniz puanınız 0.5 * 0.7 = 0.35 ile çarpılacaktır.

Faydalı bilgiler (aşağıdaki kaynaklar)

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

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

Dodecahedronun 20 köşesi vardır. Bunlardan 8'i, aşağıdaki kartezyen (x, y, z) koordinatlarına sahip bir küpün köşelerini oluşturur:

(± 1, ± 1, ± 1)

Kalan 12 aşağıdaki gibidir (phi altın orandır)

(0, ± 1 / φ, ± φ)

(± 1 / φ, ± φ, 0)

(± φ, 0, ± 1 / φ)

Küçük yıldız şeklinde dodecahedron ve büyük dodecahedronun dışbükey gövdesi açıkçası düzenli bir dodecahedron. Dış köşeler bir ikosahedronu tanımlar.

Wikipedia'ya göre bir ikosahedronun 12 köşesi, (0, ± 1, ± φ) döngüsel permütasyonlarına benzer bir şekilde tarif edilebilir. Küçük yıldızlanmış dodecaheron ve büyük dodechahedron'un dış köşeleri (yukarıdaki dodecahedron ile aynı ölçekte), daha büyük bir ikosahedron oluşturur, burada köşelerin koordinatları (0, ± φ ^ 2, ± φ) döngüsel permütasyonlarıdır.

Dodecahedron ve icosahedron için yüzler arasındaki açılar sırasıyla 2 arctan (phi) ve arccos'tur (- (√5) / 3).

Döndürmeyle ilgili ipuçları için bkz. Https://en.wikipedia.org/wiki/Rotation_matrix

EDIT: Yanlışlıkla düzenli dodecahedron izin verdim ve şimdi geri çekemiyorum. Üç yıldızlı polihedra kalıntısının hepsini çizmek için x0.7 bonusu. Yılbaşı gününde, dört mohedranın çoğunu gösterebilen cevap için, kravat kopuşu olarak en kısa kodla 100 lütuf ödeyeceğim.


@ Polihedra (örneğin dodecahedron) çizmek için kullanılan LegionMammal978 yapılarına izin verilmiyor. Bazı dillerde 3 boyutlu modeller oluşturmak için komutlar gibi olanaklar bulunur triangle[[a,b,c],[p,q,r],[x,y,z]]. Bu diller genellikle modeli döndürmek ve görüntülemek, otomatik olarak gizli yüzleri göstermemek vb. Bonusun amacı, bu olanaklara sahip olmayan dillerin rekabetçi olmasını sağlamak ve ayrıca daha ilginç çözümler çekmek.
Level River St

@ LegionMammal978 haha, Mathematica'nın sorunlara neden olan dil olacağını biliyordum. Polyhedrondataaçıkça çok yüzlü çizim için bir yapı olduğu için izin verilmiyor. Cevabınız polihedra çizmek için yerleşikleri kullanmıyorsa ve diğer kurallara uyuyorsa, kabul edilebilir. Amacınız, yüzleri doğru bir şekilde renklendirmeniz gerektiğinde, Polyhedrondatasizi çok fazla kurtaramayacağı gerçeği göz önüne alındığında, pratikte biraz keyfi bir kısıtlama olabilir. Bir dereceye kadar katılıyorum, ancak gönderdikten sonra kuralları değiştirmekten kaçınmam daha adil.
Level River St

Yanıtlar:


3

Python 2.7, 949 bayt

İşte matplotlib kullanılarak çizilen düzenli dodecahedron için çözüm. Çözülmemiş kod için kaba taslak (burada gösterilmemiştir) aşağıda özetlenmiştir:

  • Köşeleri yap Kenarları yap (en yakın 3 komşuyu temel alır, modül scipy.spatial.KDtree)
  • Uzunlukları 5 olan grafik döngülerine göre yüzler oluşturun (modül ağıx)
  • Yüz normalleri yapın (ve dışa bakan normal, numpy.cross olanları seçin)
  • Yüz normaline göre renklendirme oluşturun
  • Matplotlib kullanarak çizim yapma
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()

resim açıklamasını buraya girin


3

Yakut, 784 bayt * 0,5 * 0,7 = 274,4

Kendi cevabım, bu yüzden ödülüm için uygun değil.

Hem 3D olmayan yerleşik bonus hem de tüm yıldız çizim bonusu için uygundur.

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

Fonksiyon parametreleri olarak giriş

Düzenli dodekahedron, küçük yıldızlı dodekahedron, büyük yıldızlı dodekahedrona karşılık gelen bir tamsayı 0..3

X, y ve x (tekrar) eksenleri arasındaki dönüşler için derece açılarına karşılık gelen üç tamsayı dizisi (herhangi bir dönüşün gerçekleştirilmesini sağlayan uygun Euler açıları).

p.svgBir web tarayıcısında görüntülenebilecek bir dosya çıktısı alın .

açıklama

kodun altındaki x, y, z dizileri, küçük bir yıldız şeklinde dodekahedronun bir yüzünün dış noktalarının koordinatlarını içerir. Bu, 12 köşesi (+/- 377, + / - 233, + / - 0) döngüsel permütasyonları ile tanımlanan icosahedronda yazılabilir. 377 ve 233'ün ardışık Fibonacci sayıları olduğunu ve bu nedenle 377/233'ün altın orana mükemmel bir yaklaşım olduğunu unutmayın.

ilave bir w dizisi, x düzlemindeki yansımayla eşdeğer olarak -1 ile çarpılan x koordinatlarını içerir. F işlevi, x, y, z ve w, y, z'nin farklı döngüsel permütasyonları ile her renk için bir kez 6 kez çağrılır.

Üç dönüş n [] parametresi olarak geçirilir. Ruby'de günah ve cos kullanmak için bunu yapmak gerekir include Math. Bundan kaçınmak için, açının kosinüsü ve sinüsü -1'in kare kökünü ( "i"90 / derece cinsinden açı) bir güce yükselterek elde edilir . Bu sayının gerçek ve hayali kısımları k (kosinüs) ve l ( sinüs)

Döndürmeden önce, x ve y değerleri değiştirilir. Daha sonra, x ekseni etrafında bir dönüş vermek için y ve z değerlerine matris çarpımı uygulanır. Değerlerin değişimi, üç rotasyonun bir döngü içinde gerçekleştirilmesini sağlar.

Şimdiye kadar, sadece bir puan halkamız var. Gerisini elde etmek için beşgen / yıldızın merkezini bulmamız gerekir. Bu, p, q, r'de saklanan 5 köşenin ortalama koordinatlarını bularak yapılır.

Daha önce de belirtildiği gibi, renk başına sadece bir işlev çağrısı yapılır. R işareti (z koordinatlarının ortalaması ve dolayısıyla yüzün koordinatı) test edilir. Olumlu ise, yüz bir ön yüzdür ve bu nedenle görülebilir. Negatifse, yüz arka yüzdür. Görünmezdir ve karşıt yüz için herhangi bir fonksiyon çağrımız yoktur. Bu nedenle, her üç koordinat da ters çevrilmelidir. Bunu kolaylaştırmak için r işareti e'de saklanır.

Yüz, köşeleri küçük yıldızlı dodecahedronun dış yüzlerinin doğrusal yüzleri ve yüzün merkezi olan 5 üçgenden oluşur. Küçük yıldız şeklinde dodekahedron durumunda, üçgenlerin uçları için a = 1 ve b = 0 (p, q, r'den 1, x, y, z ve 0'dan katkı 1) ayarladık. Üçgenin 2 temel köşesi için c = -0.382 (katkı 1 / altın oranı ^ 2 x, y, z'den) ve d = 1.382 (p, q, r'den katkı) ayarladık. Olumsuz katkının nedeni üçgenin taban köşelerinin, yüzün karşı tarafında bulunan karşıt uçlar olarak tanımlandığıdır. Elde edilen koordinatlar gerektiği şekilde e ile çarpılır.

a,b,c,dDeğerleri normal dodecahedron, küçük yıldızlanmış dodecahedron, büyük dodecahedron ve büyük stellated dodecahedron için gerekli değerleri içerecek şekilde atanan dört isimsiz diziler , küçük yıldızlı tdodecahedron ve büyük dodecahedron için a + b = c + d = 1. A + b = c + d ilişkisi diğer şekiller için geçerlidir, ancak farklı bir ölçek uygulanır.

Her üçgen için bir svg kodu satırı oluşturulur. Bu, üçgenin 3 köşesinin z koordinatlarının toplamından, üçgenin üç koordinatının köşelerinin bir açıklamasından ve bir renkten türetilen bir kimlik içerir. ortografik izdüşümde z eksenini düz olarak gördüğümüze dikkat edin. Böylece 2D x = 3D x ve 2D y = 3D y. Satır eklenirh.

son olarak, tüm fonksiyon çağrıları bittikten sonra, en yüksek z değerine sahip üçgenler (önde) en son çizilecek ve her şey uygun üstbilgi ve altbilgi metnine sahip bir svg dosyası olarak kaydedilecek şekilde h sıralanır.

Test programında yönlendirilmemiş

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]

Çıktı

küçük yıldız şeklinde dodecahedron için (yakında diğer çokgenlerin bazı görüntülerini ekleyecektir)

1,0,0,0 başlangıç ​​konumu

resim açıklamasını buraya girin

1,30,0,0 30 derece aşağı döndür

resim açıklamasını buraya girin

1,0,30,0 sağ 30 derece döndür (not: mükemmel bir yan görünüm için döndürme atan(1/golden ratio)= 31,7 derece olacaktır, bu nedenle hala küçük bir mavi şerit görebiliriz)

resim açıklamasını buraya girin

1,0,20,0 sağa 20 derece döndür

resim açıklamasını buraya girin

1,60,10, -63 aşağı, sağa ve yukarı döndürme (yalnızca 3 döndürmeyle yönelim örneği)

resim açıklamasını buraya girin

0,30,0,0 düzenli dodekahedron

resim açıklamasını buraya girin

2,0,20,0 büyük dodekahedron

resim açıklamasını buraya girin

3,45,45,45 harika yıldız şeklinde dodekahedron resim açıklamasını buraya girin


3

Mathematica, 426 424 bayt

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Şekli görüntülemek için yerleşik olanı kullanır . Baytların çoğu sıkıştırılmış tepe konumları tarafından alınır, ancak bunlar daha sonra Partitionkullanılabilir bir forma dönüştürülür Polygon. En sonunda:

Bu şeklin tıklanarak ve sürüklenerek döndürülebileceğini unutmayın.


OMG, düzenli dodecahedron'u silecektim! Anlayabildiğim kadarıyla (Mathematica bilmiyorum ya da bilmiyorum) bu kurallara uygun, yani +1.
Level River St

@steveverrill Boyutu çok fazla değiştireceğini düşünmüyorum, ama bunu sıfırdan yeniden yazmak zorunda kalmamayı tercih ederim.
LegionMammal978

Cevabınız geçerli, kuralları değiştirmeyeceğim, kötü bir form olurdu. Bununla birlikte, üç yıldızlı polihedra için 0.7 bonusuna ek olarak, dört polihedranın çoğunu üretebilecek cevap için bir ödül teklif ettim. Cevabınızı güncellemeye karar verdiyseniz, koordinatları algoritmik olarak oluşturarak çok sayıda bayt kaydedebileceğinizi düşünürüm (sorunun yararlı bilgi bölümüne bakın.)
Level River St

@steveverrill, olurdu, ama görünüşe göre, tepe konumları kuartiklerin köklerini içeriyor ve bir desen bulamıyorum.
LegionMammal978
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.