Plot tessellation bidang hiperbolik

10

Buat plot (disk Poincare) dari tessellation pada bidang hiperbolik, seperti:

masukkan deskripsi gambar di sini

Program ini membutuhkan empat input:

1) Berapa banyak tepian / poligon (tiga dalam contoh ini).

2) Berapa banyak berpotongan di setiap dhuwur (tujuh dalam contoh ini).

3) Berapa banyak langkah menjauh dari titik pusat ke render (5 dalam contoh ini, jika Anda melihat lebih dekat). Ini berarti bahwa sebuah simpul disertakan jika dapat dicapai dalam 5 langkah atau kurang dari pusat. Tepi diberikan jika kedua verteksnya disertakan.

4) Resolusi gambar (jumlah piksel tunggal, gambar persegi).

Outputnya harus berupa gambar. Tepian harus diterjemahkan sebagai lingkaran-busur, bukan garis (proyeksi disk Poincaré mengubah garis menjadi lingkaran). Poin tidak perlu dirender. Ketika pengguna memasukkan sesuatu yang tidak hiperbolik (yaitu 5 pertemuan segitiga di setiap titik), program tidak harus bekerja dengan baik. Ini kode-golf, jadi jawaban terpendek menang.

Kevin Kostlan
sumber
Lebih jelas.
Kevin Kostlan
Jauh lebih jelas sekarang :)
trichoplax
Itu implisit, tetapi mungkin lebih baik untuk membuatnya eksplisit bahwa a) model disk Poincaré harus digunakan (kecuali Anda juga terbuka untuk jawaban model setengah-pesawat); b) simpul harus diletakkan di tengah cakram, dan bukan di tengah poligon.
Peter Taylor
Haruskah vertex terletak di tengah disk? Atau bisakah pusat disk menjadi pusat poligon?
DavidC
1
Ini benar-benar membutuhkan lebih banyak informasi latar belakang. Saya telah melihat beberapa situs (tidak ada yang disebutkan dalam pertanyaan) dan saya tidak dapat menemukan spesifikasi yang tepat untuk menggambar contoh gambar, apalagi kasus umum. Jika tidak ditentukan Anda mungkin mendapatkan jawaban yang tidak valid bahwa orang telah bekerja keras (misalnya saya mengerti garis non-radial diwakili sebagai busur lingkaran, tetapi seseorang mungkin mengambil jalan pintas dan melakukan garis lurus.) Juga, tampaknya panjang edgel garis-garis dari titik pusat (sebagai persentase dari jari-jari lingkaran) perlu ditentukan.
Level River St

Jawaban:

2

Mathematica, 2535 byte

Diambil dari sini (karenanya mengapa itu komunitas wiki). Tidak terlalu golf. Lihat tautan yang disediakan untuk penjelasan penulis tentang kodenya.

Juga, saya bukan ahli Mathematica, tapi saya yakin Martin bisa melakukan keajaiban pada panjang kode. Saya bahkan tidak mengerti matematika di baliknya.

Saya membiarkannya mudah dibaca, tetapi jika pertanyaannya tidak dapat ditutup, saya akan membuatnya lebih mudah dibaca dan memindahkan 2 parameter lainnya di dalam fungsi pemanggil.

Saat ini tidak valid , silakan bantu memperbaikinya:

  • Saya pikir ini menggunakan garis daripada busur.

  • Berpusat pada wajah, bukan pada titik.

HyperbolicLine[{{Px_, Py_}, {Qx_, Qy_}}] := 
 If[N[Chop[Px Qy - Py Qx]] =!= 0., 
  Circle[OrthoCentre[{{Px, Py}, {Qx, Qy}}], 
   OrthoRadius[{{Px, Py}, {Qx, Qy}}], 
   OrthoAngles[{{Px, Py}, {Qx, Qy}}]], Line[{{Px, Py}, {Qx, Qy}}]]

OrthoCentre[{{Px_, Py_}, {Qx_, Qy_}}] := 
 With[{d = 2 Px Qy - 2 Py Qx, p = 1 + Px^2, q = 1 + Qx^2 + Qy^2}, 
  If[N[d] =!= 0., {p Qy + Py^2 Qy - Py q, -p Qx - Py^2 Qx + Px q}/d, 
   ComplexInfinity]]

OrthoRadius[{{Px_, Py_}, {Qx_, Qy_}}] := 
 If[N[Chop[Px Qy - Py Qx]] =!= 0., 
  Sqrt[Total[OrthoCentre[{{Px, Py}, {Qx, Qy}}]^2] - 1], Infinity]

OrthoAngles[{{Px_, Py_}, {Qx_, Qy_}}] := 
 Block[{a, b, c = OrthoCentre[{{Px, Py}, {Qx, Qy}}]}, 
  If[(a = N[Apply[ArcTan, {Px, Py} - c]]) < 0., a = a + 2 \[Pi]];
  If[(b = N[Apply[ArcTan, {Qx, Qy} - c]]) < 0., 
   b = b + 2 \[Pi]]; {a, b} = Sort[{a, b}];
  If[b - a > \[Pi], {b, a + 2 \[Pi]}, {a, b}]]

Inversion[Circle[{Cx_, Cy_}, r_], {Px_, Py_}] := {Cx, Cy} + 
  r^2 {Px - Cx, Py - Cy}/((Cx - Px)^2 + (Cy - Py)^2)
Inversion[Circle[{Cx_, Cy_}, r_, {a_, b_}], {Px_, Py_}] := {Cx, Cy} + 
  r^2 {Px - Cx, Py - Cy}/((Cx - Px)^2 + (Cy - Py)^2)

Inversion[Circle[{Cx_, Cy_}, r_, {a_, b_}], p_Line] := 
 Map[Inversion[Circle[{Cx, Cy}, r], #] &, p, {2}]

Inversion[Circle[{Cx_, Cy_}, r_, {a_, b_}], p_Polygon] := 
 Map[Inversion[Circle[{Cx, Cy}, r], #] &, p, {2}]

Inversion[Line[{{Px_, Py_}, {Qx_, Qy_}}], {Ux_, Uy_}] := 
 With[{u = Px - Qx, 
   v = Qy - Py}, {-Ux (v^2 - u^2) - 2 u v Uy, 
    Uy (v^2 - u^2) - 2 u v Ux}/(u^2 + v^2)]
Inversion[Line[{{Px_, Py_}, {Qx_, Qy_}}], p_Polygon] := 
 Map[Inversion[Line[{{Px, Py}, {Qx, Qy}}], #] &, p, {2}]

Inversion[Circle[{Cx_, Cy_}, r_], c_List] := 
 Map[Inversion[Circle[{Cx, Cy}, r], #] &, c]


PolygonInvert[p_Polygon] := 
 Map[Inversion[HyperbolicLine[#], p] &, 
  Partition[Join[p[[1]], {p[[1, 1]]}], 2, 1]]
PolygonInvert[p_List] := Flatten[Map[PolygonInvert[#] &, p]]

LineRule = Polygon[x_] :> Line[Join[x, {x[[1]]}]];
HyperbolicLineRule = 
  Polygon[x_] :> 
   Map[HyperbolicLine, Partition[Join[x, {x[[1]]}], 2, 1]];

CentralPolygon[p_Integer, q_Integer, \[Phi]_: 0] := 
 With[{r = (Cot[\[Pi]/p] Cot[\[Pi]/q] - 1)/
     Sqrt[Cot[\[Pi]/p]^2 Cot[\[Pi]/q]^2 - 1], \[Theta] = \[Pi] Range[
       1, 2 p - 1, 2]/p}, 
  r Map[{{Cos[\[Phi]], -Sin[\[Phi]]}, {Sin[\[Phi]], Cos[\[Phi]]}}.# &,
     Transpose[{Cos[\[Theta]], Sin[\[Theta]]}]]]

PolygonUnion[p_Polygon, tol_: 10.^-10] := p
PolygonUnion[p_List, tol_: 10.^-10] := 
 With[{q = p /. Polygon[x_] :> N[Polygon[Round[x, 10.^-10]]]}, 
  DeleteDuplicates[q]]
HyperbolicTessellation[p_Integer, q_Integer, \[Phi]_, k_Integer, 
  t_: 10.^-10] := 
 Map[PolygonUnion[#, t] &, 
   NestList[PolygonInvert, Polygon[CentralPolygon[p, q, \[Phi]]], 
     k][[{-2, -1}]]] /; k > 0

HyperbolicTessellation[p_Integer, q_Integer, \[Phi]_, k_Integer, 
  t_: 10.^-10] := Polygon[CentralPolygon[p, q, \[Phi]]] /; k == 0
HyperbolicTessellationGraphics[p_Integer, q_Integer, \[Phi]_, 
  k_Integer, rule_RuleDelayed, opts___] := 
 Graphics[{Circle[{0, 0}, 1], 
   HyperbolicTessellation[p, q, \[Phi], k, 10.^-10] /. rule}, opts]

Disebut seperti:

HyperbolicTessellationGraphics[3, 7, 0., 7, HyperbolicLineRule, ImageSize -> 300, PlotLabel -> "{7,7}"]

ubin

mbomb007
sumber
1
Ini terlihat seperti tembok utama teks. +1
kirbyfan64sos
@ kirbyfan64sos Ya, menguraikan ini adalah binatang. Saya cukup yakin hanya ada beberapa perubahan yang diperlukan untuk membuatnya busur bukan garis hiperbolik. Juga, mengubah fungsi / parameter menjadi nama char tunggal akan mengurangi ukurannya banyak.
mbomb007
1
@steveverrill Ini juga garis bukan busur, yang juga salah. Saya tidak yakin bagaimana memodifikasinya untuk memperbaiki masalah yang ada. Ini CW, jadi siapa pun bisa merasa bebas untuk membantu memperbaikinya.
mbomb007
1
Saya bertanya-tanya apakah itu garis atau busur. Sulit untuk mengatakan pada resolusi rendah ini, tetapi mereka sebenarnya mungkin busur, hanya saja tidak ... arcy. Misalnya, sepertinya garis di sisi kanan poligon tengah agak bengkok ke dalam.
Reto Koradi
1
Saya memiliki pendekatan lain, berdasarkan kode orang lain, yang saya dapat pare ke 1100 byte. Tapi, begitu di-golf, kodenya menjadi tidak dapat dipahami. Saya percaya hal yang sama akan terjadi jika kami mengirimkan kiriman Anda. Saat ini, saya mencoba memahami cara kerjanya dalam format verbose.
DavidC