Traçar um mosaico de avião hiperbólico

10

Faça um gráfico (disco Poincare) de um mosaico em um plano hiperbólico, como:

insira a descrição da imagem aqui

O programa aceita quatro entradas:

1) Quantas arestas / polígono (três neste exemplo).

2) Quantas interseções em cada vértice (sete neste exemplo).

3) Quantas etapas se afastam do vértice central para renderizar (5 neste exemplo, se você olhar com atenção). Isso significa que um vértice é incluído se puder ser alcançado em 5 ou menos etapas no centro. As arestas são renderizadas se ambos os vértices estiverem incluídos.

4) A resolução da imagem (um único número de pixels, a imagem é quadrada).

A saída deve ser uma imagem. As arestas devem ser renderizadas como arcos em círculo, não em linhas (a projeção do disco de Poincaré transforma linhas em círculos). Os pontos não precisam ser renderizados. Quando o usuário coloca algo que não é hiperbólico (isto é, 5 triângulos que se encontram em cada vértice), o programa não precisa funcionar corretamente. Isso é código-golfe, então a resposta mais curta vence.

Kevin Kostlan
fonte
Tornou mais claro.
Kevin Kostlan
Muito mais clara agora :)
Trichoplax
Está implícito, mas pode ser melhor deixar explícito que a) o modelo de disco de Poincaré deve ser usado (a menos que você também esteja aberto a respostas de modelos de meio plano); b) um vértice deve ser renderizado no centro do disco, e não no centro de um polígono.
Peter Taylor
Um vértice deve estar no centro do disco? Ou o centro do disco pode ser o centro de um polígono?
DavidC
11
Isso realmente precisa de mais informações de plano de fundo. Examinei alguns sites (não há nenhum mencionado na pergunta) e não consigo descobrir a especificação exata para desenhar a figura de exemplo, muito menos o caso geral. Se não for especificado, você pode obter respostas inválidas nas quais as pessoas trabalharam muito (por exemplo, eu entendo que as linhas não radiais são representadas como arcos de círculos, mas alguém pode usar um atalho e fazer linhas retas.) o comprimento do edgel das linhas do vértice central (como uma porcentagem do raio do círculo) precisa ser especificado.
Level River St

Respostas:

2

Mathematica, 2535 bytes

Retirado daqui (por isso é wiki da comunidade). Na verdade, não jogava golfe. Veja o link fornecido para a explicação do autor sobre seu código.

Além disso, não sou especialista em Mathematica, mas aposto que Martin poderia fazer maravilhas no comprimento do código. Eu nem entendo a matemática por trás disso.

Deixei legível, mas, se a pergunta não for fechada, vou melhorar a legibilidade e mover os outros 2 parâmetros dentro da função de chamada.

Atualmente inválido , sinta-se à vontade para ajudar a melhorá-lo:

  • Eu acho que isso usa linhas ao invés de arcos.

  • Centralizado em um rosto, em vez de um 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]

Chamado como:

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

revestimento

mbomb007
fonte
11
Parece a parede final do texto. 1
kirbyfan64sos
@ kirbyfan64sos Sim, decifrar isso é uma fera. Tenho certeza de que são necessárias apenas algumas alterações para fazer arcos em vez de linhas hiperbólicas. Além disso, alterar as funções / parâmetros para nomes de caracteres únicos reduziria muito o tamanho.
Mbomb007
11
@steveverrill Também são linhas em vez de arcos, o que também está errado. Não sei como modificá-lo para corrigir qualquer problema. É CW, então qualquer um pode se sentir livre para ajudar a melhorá-lo.
mbomb007
11
Fiquei me perguntando se eram linhas ou arcos. É difícil dizer com essa baixa resolução, mas eles realmente podem ser arcos, mas não muito ... arcos. Por exemplo, parece que a linha do lado direito do polígono central está levemente dobrada para dentro.
Reto Koradi 02/09/2015
11
Eu tenho outra abordagem, baseada no código de outra pessoa, que eu consegui analisar até 1100 bytes. Mas, uma vez jogado, o código se torna indecifrável. Eu acredito que o mesmo aconteceria se jogarmos sua submissão. No momento, estou tentando entender como eles funcionam no formato detalhado.
DavidC 4/15