绘制双曲平面细分


10

在双曲平面上绘制细分图(Poincare盘),例如:

在此处输入图片说明

该程序有四个输入:

1)多少个边/多边形(在此示例中为3个)。

2)每个顶点有多少个相交(在此示例中为七个)。

3)要渲染的距离中心顶点有几步(如果仔细观察,此示例中为5)。这意味着包含一个顶点,前提是可以从中心以5步或更少的步长到达该顶点。如果同时包含两个顶点,则渲染边缘。

4)图像的分辨率(单个像素,图像为正方形)。

输出必须是图像。边缘必须渲染为圆弧,而不是直线(庞加莱圆盘投影将线变成圆)。点不需要渲染。当用户放入双曲线的内容时(即在每个顶点处有5个三角形相交),该程序不必正常工作。这是代码高尔夫球,因此最短的答案为准。


说得更清楚。
凯文·科斯特兰

现在要清楚
得多

它是隐式的,但是最好明确地指出:a)应该使用庞加莱磁盘模型(除非您也对半平面模型的答案持开放态度);b)顶点应呈现在磁盘的中心,而不是多边形的中心。
彼得·泰勒

顶点必须位于磁盘的中心吗?还是磁盘的中心可以是多边形的中心?
DavidC 2015年

1
这确实需要更多背景信息。我看过几个站点(问题中没有提到),我无法弄清楚绘制示例图的确切规范,更不用说一般情况了。如果未指定,您可能会得到人们一直在努力工作的无效答案(例如,我知道非径向线表示为圆弧,但有人可能会捷径并做直线。)而且,似乎需要指定从中心顶点开始的直线的边长(以圆半径的百分比表示)。
级圣河

Answers:


2

Mathematica,2535字节

这里获取(因此它是社区Wiki)。并不是真的那么打高尔夫球。查看提供的链接以获取作者对其代码的解释。

另外,我不是Mathematica专家,但我敢打赌Martin可以在代码长度方面做得很好。我什至不了解其背后的数学原理。

我将其保留为可读性,但是如果问题仍未解决,我将使其超越可读性,并在调用者函数内移动其他两个参数。

目前无效,请随时进行改进:

  • 我认为这是使用线条而不是弧线。

  • 集中在面而不是顶点上。

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]

像这样称呼:

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

平铺


1
这看起来像是文本的终极墙。+1
kirbyfan64sos

@ kirbyfan64sos是的,解密这是一头野兽。我敢肯定,只有几处更改才能使它成为弧形而不是双曲线。同样,将函数/参数更改为单字符名称将大大减少大小。
mbomb007'9

1
@steveverrill也是直线而不是弧线,这也是错误的。我不确定如何修改它来解决这两个问题。它是CW,因此任何人都可以随时帮助改进它。
mbomb007'9

1
我想知道是直线还是弧线。在如此低的分辨率下很难说出来,但实际上它们可能是弧线,只是不是很...弧线。例如,看起来中央多边形右侧的线稍微向内弯曲。
Reto Koradi

1
根据其他人的代码,我还有另一种方法,可以减少到1100个字节。但是,一旦打了高尔夫球,代码就变得难以理解。我相信,如果我们打高尔夫,您的提交也会一样。目前,我正在尝试了解它们以详细格式工作的方式。
DavidC
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.