Zeichnen Sie eine Tessellation der hyperbolischen Ebene

10

Erstellen Sie eine Darstellung (Poincare-Scheibe) einer Tessellation auf einer hyperbolischen Ebene, z.

Geben Sie hier die Bildbeschreibung ein

Das Programm benötigt vier Eingaben:

1) Wie viele Kanten / Polygone (drei in diesem Beispiel).

2) Wie viele schneiden sich an jedem Scheitelpunkt (in diesem Beispiel sieben).

3) Wie viele Schritte vom mittleren Scheitelpunkt entfernt, um gerendert zu werden (5 in diesem Beispiel, wenn Sie genau hinschauen). Dies bedeutet, dass ein Scheitelpunkt enthalten ist, wenn er in 5 oder weniger Schritten vom Zentrum aus erreicht werden kann. Kanten werden gerendert, wenn beide Scheitelpunkte enthalten sind.

4) Die Auflösung des Bildes (eine einzelne Anzahl von Pixeln, das Bild ist quadratisch).

Die Ausgabe muss ein Bild sein. Kanten müssen als Kreisbögen und nicht als Linien gerendert werden (die Poincaré-Scheibenprojektion verwandelt Linien in Kreise). Punkte müssen nicht gerendert werden. Wenn der Benutzer etwas eingibt, das nicht hyperbolisch ist (dh 5 Dreiecke treffen sich an jedem Scheitelpunkt), muss das Programm nicht richtig funktionieren. Dies ist Code-Golf, also gewinnt die kürzeste Antwort.

Kevin Kostlan
quelle
Klarer gemacht.
Kevin Kostlan
Jetzt viel klarer :)
Trichoplax
Es ist implizit, aber es ist möglicherweise besser, explizit zu machen, dass a) das Poincaré-Plattenmodell verwendet werden sollte (es sei denn, Sie sind auch offen für Antworten auf Modelle mit halber Ebene); b) Ein Scheitelpunkt sollte in der Mitte der Platte und nicht in der Mitte eines Polygons gerendert werden.
Peter Taylor
Muss ein Scheitelpunkt in der Mitte der Platte liegen? Oder kann die Mitte der Platte die Mitte eines Polygons sein?
DavidC
1
Dies benötigt wirklich mehr Hintergrundinformationen. Ich habe mir einige Websites angesehen (in der Frage werden keine erwähnt) und kann die genaue Spezifikation für das Zeichnen der Beispielfigur nicht herausfinden, geschweige denn den allgemeinen Fall. Wenn es nicht angegeben ist, erhalten Sie möglicherweise ungültige Antworten, an denen die Leute hart gearbeitet haben (ich verstehe zum Beispiel, dass die nicht radialen Linien als Kreisbögen dargestellt werden, aber jemand könnte eine Abkürzung nehmen und gerade Linien machen.) Außerdem scheint es Die Kantenlänge der Linien vom mittleren Scheitelpunkt (als Prozentsatz des Kreisradius) muss angegeben werden.
Level River St

Antworten:

2

Mathematica, 2535 Bytes

Von hier genommen (daher ist es das Community-Wiki). Nicht wirklich so golfen. Sehen Sie sich den bereitgestellten Link an, um die Erklärung des Autors zu seinem Code zu erhalten.

Ich bin auch kein Mathematica-Experte, aber ich wette, Martin könnte Wunder in Bezug auf die Codelänge bewirken. Ich verstehe nicht einmal die Mathematik dahinter.

Ich habe es lesbar gelassen, aber wenn die Frage nicht geschlossen wird, spiele ich es über die Lesbarkeit hinaus und verschiebe die 2 anderen Parameter innerhalb der Aufruferfunktion.

Derzeit ungültig , zögern Sie nicht, es zu verbessern:

  • Ich denke, dies verwendet eher Linien als Bögen.

  • Zentriert auf einem Gesicht und nicht auf einem Scheitelpunkt.

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]

Genannt wie:

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

Fliesen

mbomb007
quelle
1
Dies sieht aus wie die ultimative Textwand. +1
kirbyfan64sos
@ kirbyfan64sos Ja, das zu entziffern ist ein Biest. Ich bin mir ziemlich sicher, dass nur wenige Änderungen erforderlich sind, um Bögen anstelle von hyperbolischen Linien zu erstellen. Wenn Sie die Funktionen / Parameter in Einzelzeichennamen ändern, wird die Größe erheblich reduziert.
mbomb007
1
@steveverrill Es sind auch Linien statt Bögen, was auch falsch ist. Ich bin nicht sicher, wie ich es ändern soll, um eines der beiden Probleme zu beheben. Es ist CW, also kann sich jeder frei fühlen, um es zu verbessern.
mbomb007
1
Ich fragte mich, ob es Linien oder Bögen waren. Bei dieser niedrigen Auflösung ist es schwer zu sagen, aber es könnten tatsächlich Bögen sein, nur nicht sehr ... Arcy. Es sieht beispielsweise so aus, als ob die Linie auf der rechten Seite des zentralen Polygons leicht nach innen gebogen ist.
Reto Koradi
1
Ich habe einen anderen Ansatz, der auf dem Code einer anderen Person basiert und den ich auf 1100 Bytes reduzieren konnte. Nach dem Golfen ist der Code jedoch nicht mehr zu entziffern. Ich glaube, dasselbe würde passieren, wenn wir Ihre Einsendung spielen würden. Im Moment versuche ich zu verstehen, wie sie im ausführlichen Format funktionieren.
DavidC