Trazar un mosaico de plano hiperbólico

10

Haga un diagrama (disco Poincare) de una teselación en un plano hiperbólico, como:

ingrese la descripción de la imagen aquí

El programa toma cuatro entradas:

1) Cuántos bordes / polígono (tres en este ejemplo).

2) Cuántos se cruzan en cada vértice (siete en este ejemplo).

3) Cuántos pasos se alejan del vértice central para renderizar (5 en este ejemplo, si se mira de cerca) Esto significa que se incluye un vértice si se puede alcanzar en 5 o menos pasos desde el centro. Los bordes se representan si se incluyen ambos vértices.

4) La resolución de la imagen (un solo número de píxeles, la imagen es cuadrada).

El resultado debe ser una imagen. Los bordes se deben representar como arcos circulares, no como líneas (la proyección del disco de Poincaré convierte las líneas en círculos). Los puntos no necesitan ser prestados. Cuando el usuario coloca algo que no es hiperbólico (es decir, 5 triángulos que se encuentran en cada vértice), el programa no tiene que funcionar correctamente. Este es el código de golf, por lo que gana la respuesta más corta.

Kevin Kostlan
fuente
Aclarado más.
Kevin Kostlan
Mucho más claro ahora :)
trichoplax
Está implícito, pero podría ser mejor hacer explícito que a) se debe usar el modelo de disco de Poincaré (a menos que también esté abierto a las respuestas del modelo de medio plano); b) se debe representar un vértice en el centro del disco y no en el centro de un polígono.
Peter Taylor
¿Debe un vértice estar en el centro del disco? ¿O puede el centro del disco ser el centro de un polígono?
DavidC
1
Esto realmente necesita más información de fondo. He visto un par de sitios (no se menciona ninguno en la pregunta) y no puedo determinar la especificación exacta para dibujar la figura de ejemplo, y mucho menos el caso general. Si no se especifica, puede obtener respuestas no válidas en las que la gente ha trabajado duro (por ejemplo, entiendo que las líneas no radiales se representan como arcos de círculos, pero alguien podría tomar un atajo y hacer líneas rectas). Además, parece la longitud del borde de las líneas desde el vértice central (como un porcentaje del radio del círculo) debe especificarse.
Level River St

Respuestas:

2

Mathematica, 2535 bytes

Tomado de aquí (de ahí por qué es el wiki de la comunidad). Realmente no tan golfizado. Vea el enlace proporcionado para la explicación del autor de su código.

Además, no soy un experto en Mathematica, pero apuesto a que Martin podría hacer maravillas en la longitud del código. Ni siquiera entiendo las matemáticas detrás de esto.

Lo dejé legible, pero si la pregunta no se cierra, jugaré más allá de la legibilidad y moveré los otros 2 parámetros dentro de la función de llamada.

Actualmente inválido , siéntase libre de ayudar a mejorarlo:

  • Creo que esto usa líneas en lugar de arcos.

  • Centrado en una cara, en lugar de un vértice.

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]

Llamado como:

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

embaldosado

mbomb007
fuente
1
Esto parece el último muro de texto. +1
kirbyfan64sos
@ kirbyfan64sos Sí, descifrar esto es una bestia. Estoy bastante seguro de que solo son necesarios algunos cambios para convertirlo en arcos en lugar de líneas hiperbólicas. Además, cambiar las funciones / parámetros a nombres de caracteres individuales reduciría mucho el tamaño.
mbomb007
1
@steveverrill También son líneas en lugar de arcos, lo que también está mal. No estoy seguro de cómo modificarlo para solucionar cualquiera de los problemas. Es CW, por lo que cualquiera puede sentirse libre de ayudar a mejorarlo.
mbomb007
1
Me preguntaba si eran líneas o arcos. Es difícil saberlo con esta baja resolución, pero en realidad podrían ser arcos, pero no muy ... arcy. Por ejemplo, parece que la línea en el lado derecho del polígono central está ligeramente doblada hacia adentro.
Reto Koradi
1
Tengo otro enfoque, basado en el código de otra persona, que he podido reducir a 1100 bytes. Pero, una vez jugado, el código se vuelve indescifrable. Creo que lo mismo sucedería si jugamos su presentación. Por el momento, estoy tratando de entender cómo funcionan en formato detallado.
DavidC