-
Notifications
You must be signed in to change notification settings - Fork 10
ExamplePoincare
- summary Square on the Poincaré disk
- labels Example,Version1
_(This page applies only to the 1.x branch of SVGFig.)_
(Okay, so it's not actually a _square_, because the sides are not [http://en.wikipedia.org/wiki/Geodesic geodesics] on the hyperbolic plane. But to my Euclidean eyes, the middle one looks like a square!)
This is a grand example of recursion self-similarity: a tiling of the [http://en.wikipedia.org/wiki/Hyperbolic_plane hyperbolic plane], represented by the [http://en.wikipedia.org/wiki/Poincare_disk Poincaré disk] (one of M.C. Escher's favorite paradigms). The same [ClassPath Path] is drawn 5 iterations deep, transformed with the appropriate [http://en.wikipedia.org/wiki/M%C3%B6bius_transformation Möbius transformation]. This is perhaps the simplest case, in which the tiles are generated by the [http://en.wikipedia.org/wiki/Free_group free group].
Yes, I just learned a little [http://en.wikipedia.org/wiki/Riemannian_geometry Riemannian geometry] and was itching to draw this.
from svgfig import * import math def one(z): return (z + (1+1j)/2.) / ((1-1j)*z/2. + 1) def two(z): return (z + -(1-1j)/2.) / (-(1+1j)*z/2. + 1) def three(z): return (z - (1+1j)/2.) / (-(1-1j)*z/2. + 1) def four(z): return (z + (1-1j)/2.) / ((1+1j)*z/2. + 1) def recurse(t, direction, depth=0): if depth == 5: return Fig() if direction == one: return Fig(t, recurse(t, two, depth+1), recurse(t, one, depth+1), recurse(t, four, depth+1), trans=totrans(one)) if direction == two: return Fig(t, recurse(t, three, depth+1), recurse(t, two, depth+1), recurse(t, one, depth+1), trans=totrans(two)) if direction == three: return Fig(t, recurse(t, four, depth+1), recurse(t, three, depth+1), recurse(t, two, depth+1), trans=totrans(three)) if direction == four: return Fig(t, recurse(t, one, depth+1), recurse(t, four, depth+1), recurse(t, three, depth+1), trans=totrans(four)) x = 1. - math.sqrt(0.5) tile = Path("M -%g -%g L -%g %g L %g %g L %g -%g Z" % ((x,) * 8), fill="purple") Fig(Ellipse(0, 0, 0, 1, 1, fill="lightgreen"), \ tile, \ recurse(tile, one), \ recurse(tile, two), \ recurse(tile, three), \ recurse(tile, four)).SVG(window(-1.1, 1.1, -1.1, 1.1)).inkview()
- Note that we could have loaded a <path /> from a file: we can tile the hyperbolic plane with _anything!_
- Only the vertices are transformed, not the edges of the [ClassPath Path]. We could have replaced the [ClassPath Path] with a [ClassRect Rect]. That would have curved the edges, but it takes a long time. Perhaps the adaptive sampling algorithm could be optimized or compiled.
[http://svgfig.googlecode.com/svn/wiki/ExamplePoincare.svg http://svgfig.googlecode.com/svn/wiki/ExamplePoincare.png] | ||
[http://svgfig.googlecode.com/svn/wiki/ExamplePoincare.svg ExamplePoincare.svg] |